private void ReadDefineClass(Int64 timeStamp, int eventLength, IBinaryLogDataStream stream) { UInt32 classId = stream.ReadUInt32(); UInt32 numElements = stream.ReadUInt32(); byte[] descBytes = stream.ReadBytes(eventLength - 8); IIntervalSink sink = m_sinks[classId]; Type propType = sink.PropertiesType; EventPropertyDesc[] properties = new EventPropertyDesc[numElements]; int p = 0; for (UInt32 elementIdx = 0; elementIdx < numElements; ++elementIdx) { byte typeId = descBytes[p++]; int nullTermIdx = Array.IndexOf <byte>(descBytes, 0, p); string name = System.Text.Encoding.ASCII.GetString(descBytes, p, (nullTermIdx >= 0 ? nullTermIdx : descBytes.Length) - p); p = nullTermIdx + 1; // Find a field with the same name in the C# type FieldInfo field = propType.GetField(name, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); properties[elementIdx] = new EventPropertyDesc((EFrameElementType)typeId, field); } m_classDescs[classId] = new EventClassDesc(propType, properties); }
public void ProcessDataStream() { CultureInfo decimalCulture = new CultureInfo("en-US"); Regex callstackAddressesRegex = new Regex(@"0x[0-9|a-f|A-F]*"); IIntervalSink[] ivSinks = new IIntervalSink[] { new StreamingIntervalSink(m_logData), new StreamingObjectSink(m_logData, "/Objects", 111), new StreamingTextureSink(m_logData, "/Textures", 116), }; EventReader eventReader = new EventReader(ivSinks); try { //Endian byte[] endianByte = m_logDataStream.ReadBytes(1); EEndian endian = (EEndian)endianByte[0]; m_logDataStream.SetEndian(endian); //Version UInt32 version = m_logDataStream.ReadUInt32(); if (version > STATOSCOPE_BINARY_VERSION) { throw new Exception("Binary file version mismatch"); } m_logVersion = version; //Using string pool? m_bUsingStringPool = m_logDataStream.ReadBool(); List <KeyValuePair <string, EItemType> > newmds = new List <KeyValuePair <string, EItemType> >(); FrameRecordPathCollection paths = new FrameRecordPathCollection(); while (!m_logDataStream.IsEndOfStream) { // header present if (m_logDataStream.ReadBool()) { // modules present if (m_logDataStream.ReadBool()) { ReadModules(); } ReadFormat(); } //FRAME RECORD BEGIN FrameRecordValues values = new FrameRecordValues(paths); float frameTimeInS = 0.0f; MemoryStream screenshotImage = null; List <UserMarker> userMarkers = new List <UserMarker>(); List <Callstack> callstacks = new List <Callstack>(); //check for fps or screen shot float frameTimeValue = m_logDataStream.ReadFloat(); if (frameTimeValue > 0) { frameTimeInS = (float)Convert.ToDouble(frameTimeValue, decimalCulture); } EFrameElementType type = ReadFrameElementType(); if (type == EFrameElementType.B64Texture) { //process texture int size = m_logDataStream.ReadInt32(); byte[] screenShotBytes = m_logDataStream.ReadBytes(size); screenshotImage = ImageProcessor.CreateImageStreamFromScreenshotBytes(screenShotBytes); } //On to specific data groups foreach (PerfStatLogLineDescriptor lld in m_logLineDescriptors) { //number of stats, so records have a variable number of entries, like frame profiler int nStats = m_logDataStream.ReadInt32(); for (int i = 0; i < nStats; i++) { string path = lld.m_path; foreach (PerfStatFrameElement fe in lld.m_formatElements) { if (fe.m_type == EFrameElementType.String && fe.m_name.Equals("path")) { // Replace first occurrence of "$" in path with its placeholder value string valueString = ReadString(); StringBuilder sbModifiedString = new StringBuilder(path); sbModifiedString.Replace("$", valueString, path.IndexOf("$"), 1); path = sbModifiedString.ToString(); } else { switch (fe.m_type) { case EFrameElementType.Float: { float value = m_logDataStream.ReadFloat(); string itemname = path + fe.m_name; values[itemname] += value; // += as there may be duplicate records per frame newmds.Add(new KeyValuePair <string, EItemType>(itemname, EItemType.Float)); } break; case EFrameElementType.Int: { int value = m_logDataStream.ReadInt32(); string itemname = path + fe.m_name; values[itemname] += (float)value; // += as there may be duplicate records per frame newmds.Add(new KeyValuePair <string, EItemType>(itemname, EItemType.Int)); } break; case EFrameElementType.B64Texture: throw new Exception("Screen shot in frame profiler not supported"); //break; case EFrameElementType.String: string userMarkersInitialPath = "/UserMarkers/"; string callstacksInitialPath = "/Callstacks/"; string valueString = ReadString(); if (path.StartsWith(userMarkersInitialPath)) { string pathNoEndSlash = path.TrimEnd(new char[] { '/' }); // old format compatibility UserMarker userMarker = new UserMarker(pathNoEndSlash, valueString); userMarkers.Add(userMarker); } else if (path.StartsWith(callstacksInitialPath)) { Callstack callstack = new Callstack(path.Substring(callstacksInitialPath.Length)); MatchCollection addressesMatches = callstackAddressesRegex.Matches(valueString); foreach (Match addressMatch in addressesMatches) { UInt32 address = Convert.ToUInt32(addressMatch.Value, 16); callstack.m_functions.Add(GetSymbolNameFromAddress(address)); } callstack.m_functions.Reverse(); callstacks.Add(callstack); } break; } } } } } if (version > 1) { eventReader.ReadEvents(m_logDataStream); } UInt32 magic = m_logDataStream.ReadUInt32(); if (magic != 0xdeadbeef) { throw new Exception("Frame Record is corrupt"); } for (int si = 0, sc = ivSinks.Length; si != sc; ++si) { ivSinks[si].OnFrameRecord(values); } FrameRecord fr = new FrameRecord(m_logData.FrameRecords.Count, frameTimeInS, screenshotImage, m_logData.CreateNewFrameRecordValues(values), userMarkers, callstacks); m_logData.AddFrameRecord(fr, newmds); m_logDataStream.FlushWriteStream(); newmds.Clear(); } } catch (Exception ex) { Console.WriteLine(ex); } foreach (var resolver in m_symbolResolvers) { resolver.Dispose(); } m_symbolResolvers.Clear(); m_logDataStream.CloseWriteStream(); }