Stop allocating when enumerating events

Previously we would allocate objects to keep track of state for more
complicated LTTng events.  Now we track state within the buffer so that
we can refer back to sizes of arrays...eliminating the need to keep
track of most state.
This commit is contained in:
Lee Culver
2016-07-07 11:26:24 -07:00
parent 0084494377
commit 8dd66a7186
5 changed files with 348 additions and 535 deletions
+7 -88
View File
@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace Microsoft.Diagnostics.Tracing.Ctf
{
@@ -22,18 +23,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
Load(parser);
}
internal void WriteMetadata(TextWriter output)
{
Trace.WriteLine(output, 0);
Environment.WriteLine(output, 0);
foreach (CtfClock clock in _clocks.Values)
clock.WriteLine(output, 0);
foreach (CtfStream stream in Streams)
stream.WriteLine(output, 0);
}
public void Load(CtfMetadataParser parser)
{
Dictionary<string, CtfMetadataType> typeAlias = new Dictionary<string, CtfMetadataType>();
@@ -125,7 +114,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
output.WriteLine("{0} Byte order: {1}", ind, ByteOrder);
output.WriteLine("{0} Header:", ind);
Header.WriteLine(output, null, indent + 4);
output.WriteLine();
}
@@ -180,23 +168,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
foreach (CtfEvent evt in _events)
evt.ResolveReferences(typealias);
}
internal void WriteLine(TextWriter output, int indent)
{
string ind = new string(' ', indent);
output.WriteLine("{0}Stream {1}:", ind, ID);
output.WriteLine("{0} Header:", ind);
EventHeader.WriteLine(output, null, indent + 8);
output.WriteLine("{0} PacketContext:", ind);
PacketContext.WriteLine(output, null, indent + 8);
output.WriteLine("{0} Events:", ind);
foreach (CtfEvent evt in _events)
evt.WriteLine(output, null, indent + 8);
output.WriteLine();
}
}
/// <summary>
@@ -218,16 +189,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public string TracerName { get; private set; }
public int TracerMajor { get; private set; }
public int TracerMinor { get; private set; }
internal void WriteLine(TextWriter output, int indent)
{
string ind = new string(' ', indent);
output.WriteLine("{0}Environment:", ind);
output.WriteLine("{0} Host name: {1}", ind, HostName);
output.WriteLine("{0} Domain: {1}", ind, Domain);
output.WriteLine("{0} Tracer: {1} ({2}.{3})", ind, TracerName, TracerMajor, TracerMinor);
output.WriteLine();
}
}
@@ -250,17 +211,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public string Name { get; private set; }
public ulong Offset { get; private set; }
public Guid UUID { get; private set; }
internal void WriteLine(TextWriter output, int indent)
{
string ind = new string(' ', indent);
output.WriteLine("{0}Clock:", ind);
output.WriteLine("{0} Name: {1}", ind, Name);
output.WriteLine("{0} Description: {1}", ind, Description);
output.WriteLine("{0} UUID: {1}", ind, UUID);
output.WriteLine("{0} Offset: {1}", ind, Offset);
output.WriteLine();
}
}
/// <summary>
@@ -281,7 +231,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
get
{
if (_size == SizeUninitialized)
_size = Fields.GetSize();
_size = Definition.GetSize();
Debug.Assert(_size >= SizeIndeterminate);
return _size;
@@ -292,14 +242,14 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public string Name { get; private set; }
public int Stream { get; private set; }
public uint LogLevel { get; private set; }
public CtfStruct Fields { get; private set; }
public CtfStruct Definition { get; private set; }
public bool IsPacked
{
get
{
if (!_isPacked.HasValue)
{
var fields = Fields.Fields;
var fields = Definition.Fields;
_isPacked = fields.Length == 3 && fields[2].Name == "___data__";
}
@@ -314,43 +264,12 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
Stream = bag.GetInt("stream_id");
LogLevel = bag.GetUInt("loglevel");
Fields = bag.GetStruct("fields");
Definition = bag.GetStruct("fields");
}
internal void ResolveReferences(Dictionary<string, CtfMetadataType> typealias)
{
Fields.ResolveReference(typealias);
}
internal void WriteLine(TextWriter output, object[] values, int indent)
{
string ind = new string(' ', indent);
output.WriteLine("{0}Event {1}:", ind, ID);
output.WriteLine("{0} Name: {1}", ind, Name);
output.WriteLine("{0} LogLevel: {1}", ind, LogLevel);
var actualFields = Fields.Fields;
if (actualFields.Length > 0)
{
output.WriteLine("{0} Fields:", ind);
if (values == null)
{
foreach (CtfField field in actualFields)
field.WriteLine(output, null, indent + 8);
}
else
{
for (int i = 0; i < actualFields.Length; i++)
actualFields[i].WriteLine(output, values[i], indent + 8);
}
}
else
{
output.WriteLine("{0} No fields.", ind);
}
output.WriteLine();
Definition.ResolveReference(typealias);
}
public override string ToString()
@@ -360,7 +279,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public int GetFieldOffset(string name)
{
return Fields.GetFieldOffset(name);
return Definition.GetFieldOffset(name);
}
}
}
@@ -24,8 +24,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
static Regex s_struct = new Regex(@"^\s*struct\s(\{|\w+)");
static Regex s_float = new Regex(@"floating_point +\{");
static CtfString s_string = new CtfString();
private Stream _stream;
public CtfMetadataLegacyParser(string filename)
@@ -255,7 +253,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
string typeName = typeGroup.ToString().Trim();
if (typeName == "string")
type = s_string;
type = new CtfString();
else
type = new CtfUnresolvedType(typeName);
+161 -153
View File
@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
namespace Microsoft.Diagnostics.Tracing.Ctf
{
@@ -54,6 +55,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
abstract class CtfMetadataType
{
public int BitOffset { get; set; }
public abstract int Align { get; }
public CtfTypes CtfType { get; protected set; }
@@ -64,15 +66,9 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
}
internal abstract CtfMetadataType ResolveReference(Dictionary<string, CtfMetadataType> typealias);
internal abstract void Write(TextWriter output, object value, int indent);
internal virtual void WriteLine(TextWriter output, object value, int indent)
{
Write(output, value, indent);
output.WriteLine();
}
public abstract int GetSize();
public abstract object Read(byte[] buffer);
}
/// <summary>
@@ -110,12 +106,12 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
return typealias[Name];
}
internal override void Write(TextWriter output, object value, int indent)
public override int GetSize()
{
output.Write("{0}{1}", new string(' ', indent), Name);
throw new InvalidOperationException();
}
public override int GetSize()
public override object Read(byte[] buffer)
{
throw new InvalidOperationException();
}
@@ -151,30 +147,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
Type = Type.ResolveReference(typealias);
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
output.Write("{0}{1}[{2}]", new string(' ', indent), Type, Index);
if (value != null)
{
output.Write("{ ");
output.Write(string.Join(", ", (object[])value));
output.Write(" }");
}
}
public int GetLength(CtfStruct strct, object[] values)
{
int len;
if (int.TryParse(Index, out len))
return len;
return strct.GetFieldValue<int>(values, Index);
}
public override int GetSize()
{
@@ -188,6 +160,11 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
return size * len;
}
public override object Read(byte[] buffer)
{
return new byte[0];
}
}
class CtfFloat : CtfMetadataType
@@ -212,24 +189,22 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public string ByteOrder { get; private set; }
public int Exp { get; private set; }
public int Mant { get; private set; }
internal override CtfMetadataType ResolveReference(Dictionary<string, CtfMetadataType> typealias)
{
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
output.Write("{0}float", new string(' ', indent));
if (value != null)
output.Write(" " + value.ToString());
}
public override int GetSize()
{
return Exp + Mant;
}
public override object Read(byte[] buffer)
{
// TODO: We don't support reading floats.
return 0f;
}
}
class CtfInteger : CtfMetadataType
@@ -269,21 +244,126 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
{
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
output.Write("{0}{1}int{2}", new string(' ', indent), Signed ? "" : "u", Size);
if (value != null)
output.Write(" " + value.ToString());
}
public override int GetSize()
{
return Size;
}
public static T ReadInt<T>(CtfMetadataType type, byte[] buffer, int bitOffset) where T : IConvertible
{
if (type.CtfType == CtfTypes.Enum)
type = ((CtfEnum)type).Type;
CtfInteger intType = (CtfInteger)type;
object result = intType.Read(buffer, bitOffset);
object converted = ((IConvertible)result).ToType(typeof(T), null);
return (T)converted;
}
public object Read(byte[] buffer, int bitOffset)
{
if (Size > 64)
throw new NotImplementedException();
Debug.Assert((bitOffset % Align) == 0);
int byteOffset = bitOffset / 8;
bool fastPath = (bitOffset % 8) == 0 && (Size % 8) == 0;
if (fastPath)
{
if (Size == 32)
{
if (Signed)
return ((IConvertible)BitConverter.ToInt32(buffer, byteOffset));
return BitConverter.ToUInt32(buffer, byteOffset);
}
if (Size == 8)
{
if (Signed)
return (sbyte)buffer[byteOffset];
return buffer[byteOffset];
}
if (Size == 64)
{
if (Signed)
return BitConverter.ToInt64(buffer, byteOffset);
return BitConverter.ToUInt64(buffer, byteOffset);
}
Debug.Assert(Size == 16);
if (Signed)
return BitConverter.ToInt16(buffer, byteOffset);
return BitConverter.ToUInt16(buffer, byteOffset);
}
// Sloooow path for misaligned integers
int bits = Size;
ulong value = 0;
int byteLen = IntHelpers.AlignUp(bits, 8) / 8;
for (int i = 0; i < byteLen; i++)
value = unchecked((value << 8) | buffer[byteOffset + byteLen - i - 1]);
value >>= bitOffset;
value &= (ulong)((1 << bits) - 1);
if (Signed)
{
ulong signBit = (1u << (bits - 1));
if ((value & signBit) != 0)
value |= ulong.MaxValue << bits;
}
if (Size > 32)
{
if (Signed)
return (long)value;
return value;
}
if (Size > 16)
{
if (Signed)
return (int)value;
return (uint)value;
}
if (Size > 8)
{
if (Signed)
return (short)value;
return (ushort)value;
}
if (Signed)
return (sbyte)value;
return (byte)value;
}
public override object Read(byte[] buffer)
{
return Read(buffer, BitOffset);
}
}
class CtfString : CtfMetadataType
{
public int Length { get; set; }
public override int Align
{
get
@@ -308,20 +388,16 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
{
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
string ind = new string(' ', indent);
if (value != null)
output.Write(ind + '"' + value.ToString() + '"');
else
output.Write("{0}string", ind);
}
public override int GetSize()
{
return CtfEvent.SizeIndeterminate;
}
public override object Read(byte[] buffer)
{
return Encoding.Unicode.GetString(buffer, BitOffset >> 3, Length);
}
}
class CtfEnum : CtfMetadataType
@@ -349,15 +425,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
Type = Type.ResolveReference(typealias);
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
string ind = new string(' ', indent);
if (value == null)
output.Write("{0}enum {{ {1} }}", ind, string.Join(", ", Values));
else
output.Write("{0} - {1}", GetName(((IConvertible)value).ToInt32(null)), value);
}
internal string GetName(int value)
{
foreach (CtfNamedRange range in Values)
@@ -371,6 +439,17 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
{
return Type.GetSize();
}
internal CtfNamedRange GetValue(string name)
{
return Values.Where(p => p.Name == name).Single();
}
public override object Read(byte[] buffer)
{
int value = CtfInteger.ReadInt<int>(Type, buffer, BitOffset);
return GetName(value);
}
}
class CtfStruct : CtfMetadataType
@@ -409,27 +488,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
_resolved = true;
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
output.WriteLine("{0}struct", new string(' ', indent));
output.WriteLine(new string(' ', indent) + "{");
if (value == null)
{
foreach (CtfField field in Fields)
field.WriteLine(output, null, indent + 4);
}
else
{
object[] values = (object[])value;
for (int i = 0; i < Fields.Length; i++)
Fields[i].WriteLine(output, values[i], indent + 4);
}
output.Write(new string(' ', indent) + "}");
}
internal CtfField GetField(string name)
{
for (int index = 0; index < Fields.Length; index++)
@@ -439,34 +498,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
return null;
}
internal T GetFieldValue<T>(object[] result, string name)
{
int index = GetFieldIndex(name);
return GetFieldValue<T>(result, index);
}
internal T GetFieldValue<T>(object[] result, int index)
{
object o = result[index];
if (!(o is T))
o = ((IConvertible)o).ToType(typeof(T), null);
return (T)o;
}
internal int GetFieldIndex(string name)
{
int index = 0;
for (; index < Fields.Length; index++)
if (Fields[index].Name == name)
break;
if (index == Fields.Length)
throw new ArgumentException("name");
return index;
}
public override int GetSize()
{
int size = 0;
@@ -499,6 +530,11 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
throw new ArgumentException();
}
public override object Read(byte[] buffer)
{
throw new InvalidOperationException();
}
}
class CtfVariant : CtfMetadataType
@@ -532,26 +568,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
return this;
}
internal override void Write(TextWriter output, object value, int indent)
{
string ind = new string(' ', indent);
output.WriteLine("{0}variant <{1}>", ind, Switch);
output.WriteLine(ind + "{");
foreach (CtfField field in Union)
field.WriteLine(output, null, indent + 4);
if (value != null)
{
if (value is object[])
output.WriteLine("{0}{{ {1} }}", ind, string.Join(", ", (object[])value));
else
output.Write(ind + value);
}
output.Write(ind + "}");
}
internal CtfField GetVariant(string name)
{
return Union.Where(f => f.Name == name).Single();
@@ -575,10 +591,16 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
return size;
}
public override object Read(byte[] buffer)
{
throw new NotImplementedException();
}
}
class CtfField
{
public int BitOffset { get; set; }
public CtfMetadataType Type { get; private set; }
public string Name { get; private set; }
@@ -598,23 +620,9 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
Type = Type.ResolveReference(typealias);
}
internal void Write(TextWriter output, object value, int indent)
internal object Read(byte[] buffer)
{
if (Type.CtfType == CtfTypes.Array)
{
Type.Write(output, value, indent);
}
else
{
Type.Write(output, null, indent);
output.Write(" {0} = {1};", Name, value);
}
}
internal void WriteLine(TextWriter output, object value, int indent)
{
Write(output, value, indent);
output.WriteLine();
return Type.Read(buffer);
}
}
+174 -283
View File
@@ -82,14 +82,42 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
public IEnumerable<CtfEventHeader> EnumerateEventHeaders()
{
CtfStruct header = _streamDefinition.EventHeader;
CtfEnum id = (CtfEnum)header.GetField("id").Type;
CtfVariant v = (CtfVariant)header.GetField("v").Type;
CtfStruct extended = (CtfStruct)v.GetVariant("extended").Type;
CtfStruct compact = (CtfStruct)v.GetVariant("compact").Type;
CtfInteger extendedId = (CtfInteger)extended.GetField("id").Type;
CtfInteger extendedTimestamp = (CtfInteger)extended.GetField("timestamp").Type;
CtfInteger compactTimestamp = (CtfInteger)((CtfStruct)v.GetVariant("compact").Type).GetField("timestamp").Type;
CtfInteger pid = null;
CtfInteger tid = null;
CtfArray processName = null;
string lastProcessName = "";
int processLen = 0;
CtfStruct eventContext = _streamDefinition.EventContext;
if (eventContext != null)
{
pid = (CtfInteger)eventContext.GetField("_vpid")?.Type;
tid = (CtfInteger)eventContext.GetField("_vtid")?.Type;
processName = (CtfArray)eventContext.GetField("_procname")?.Type;
// We only handle ascii process names, which seems to be the only thing lttng provides.
if (processName != null)
{
processLen = int.Parse(processName.Index);
Debug.Assert(processName.Type.GetSize() == 8);
if (processName.Type.GetSize() != 8)
processName = null;
}
}
uint extendedIdValue = (uint)id.GetValue("extended").End;
ulong lowMask = 0, highMask = 0, overflowBit = 0;
ulong lastTimestamp = 0;
StringBuilder processName = new StringBuilder();
while (!_eof)
{
if (_readHeader)
@@ -97,32 +125,29 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
_header.Clear();
ResetBuffer();
object[] result = ReadStruct(header);
ReadStruct(header);
if (_eof)
break;
ulong timestamp;
CtfEnum en = (CtfEnum)header.GetField("id").Type;
uint event_id = header.GetFieldValue<uint>(result, "id");
uint event_id = CtfInteger.ReadInt<uint>(id.Type, _buffer, id.BitOffset);
result = header.GetFieldValue<object[]>(result, "v");
if (en.GetName((int)event_id) == "extended")
if (event_id == extendedIdValue)
{
event_id = extended.GetFieldValue<uint>(result, "id");
timestamp = extended.GetFieldValue<ulong>(result, "timestamp");
event_id = CtfInteger.ReadInt<uint>(extendedId, _buffer, extendedId.BitOffset);
timestamp = CtfInteger.ReadInt<ulong>(extendedTimestamp, _buffer, extendedTimestamp.BitOffset);
}
else
{
if (overflowBit == 0)
{
CtfInteger compactTimestamp = (CtfInteger)compact.GetField("timestamp").Type;
overflowBit = (1ul << compactTimestamp.Size);
lowMask = overflowBit - 1;
highMask = ~lowMask;
}
ulong uint27timestamp = compact.GetFieldValue<ulong>(result, "timestamp");
ulong uint27timestamp = CtfInteger.ReadInt<ulong>(compactTimestamp, _buffer, compactTimestamp.BitOffset);
ulong prevLowerBits = lastTimestamp & lowMask;
if (prevLowerBits < uint27timestamp)
@@ -141,27 +166,40 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
CtfEvent evt = _streamDefinition.Events[(int)event_id];
_header.Event = evt;
_header.Timestamp = timestamp;
CtfStruct eventContext = _streamDefinition.EventContext;
if (eventContext != null)
{
result = ReadStruct(eventContext);
_header.Pid = eventContext.GetFieldValue<int>(result, "_vpid");
_header.Tid = eventContext.GetFieldValue<int>(result, "_vtid");
ReadStruct(eventContext);
int procnameIndex = eventContext.GetFieldIndex("_procname");
object[] procname = (object[])(result[procnameIndex]);
processName.Clear();
for (int i = 0; i < 17; i++)
if (pid != null)
_header.Pid = CtfInteger.ReadInt<int>(pid, _buffer, pid.BitOffset);
if (tid != null)
_header.Tid = CtfInteger.ReadInt<int>(tid, _buffer, tid.BitOffset);
bool matches = true;
int processNameOffset = processName.BitOffset >> 3;
if (_buffer[processNameOffset] == 0)
{
sbyte b = (sbyte)procname[i];
if (b == 0)
break;
lastProcessName = string.Empty;
}
else
{
int len = 0;
for (; len < processLen && _buffer[processNameOffset + len] != 0; len++)
{
if (len >= lastProcessName.Length)
matches = false;
else
matches &= lastProcessName[len] == _buffer[processNameOffset + len];
}
processName.Append((char)b);
if (!matches || len != lastProcessName.Length)
lastProcessName = Encoding.UTF8.GetString(_buffer, processName.BitOffset >> 3, len);
}
_header.ProcessName = processName.ToString();
_header.ProcessName = lastProcessName;
}
_readHeader = true;
@@ -174,27 +212,6 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
_bitOffset = 0;
_bufferLength = 0;
}
public object[] ReadEvent(CtfEvent evt)
{
if (!_readHeader)
throw new InvalidOperationException("Must read an event's header before reading an event's data.");
object[] result = null;
if (evt.IsPacked)
{
ReadPackedEvent();
}
else
{
ResetBuffer();
result = ReadStruct(evt.Fields);
}
_readHeader = false;
return result;
}
internal void ReadEventIntoBuffer(CtfEvent evt)
{
@@ -208,11 +225,7 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
else
{
ResetBuffer();
if (evt.IsFixedSize)
ReadBits(evt.Size);
else
ReadStruct(evt.Fields);
ReadStruct(evt.Definition);
}
_readHeader = false;
@@ -229,171 +242,153 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
ResetBuffer();
ReadBits(8 * len);
}
public object[] ReadStruct(CtfStruct strct)
public void ReadStruct(CtfStruct strct)
{
var fields = strct.Fields;
object[] result = new object[fields.Length];
for (int i = 0; i < fields.Length; i++)
result[i] = ReadType(strct, result, fields[i].Type);
return result;
ReadTypeIntoBuffer(strct, fields[i].Type);
}
private object ReadType(CtfStruct strct, object[] result, CtfMetadataType type)
public void ReadTypeIntoBuffer(CtfStruct context, CtfMetadataType type)
{
Align(type.Align);
type.BitOffset = _bitOffset;
if (type.CtfType == CtfTypes.Enum)
{
type = ((CtfEnum)type).Type;
type.BitOffset = _bitOffset;
}
else if (type.CtfType != CtfTypes.Struct && type.CtfType != CtfTypes.Variant)
{
int size = type.GetSize();
if (size != CtfEvent.SizeIndeterminate)
{
ReadBits(size);
return;
}
}
switch (type.CtfType)
{
case CtfTypes.Array:
CtfArray array = (CtfArray)type;
int len = array.GetLength(strct, result);
object[] ret = new object[len];
var indexType = context.GetField(array.Index).Type;
int len = CtfInteger.ReadInt<int>(indexType, _buffer, indexType.BitOffset);
for (int j = 0; j < len; j++)
ret[j] = ReadType(null, null, array.Type);
return ret;
case CtfTypes.Enum:
return ReadType(strct, result, ((CtfEnum)type).Type);
int elemSize = array.Type.GetSize();
if (elemSize == CtfEvent.SizeIndeterminate)
{
for (int j = 0; j < len; j++)
ReadTypeIntoBuffer(null, array.Type);
}
else
{
for (int j = 0; j < len; j++)
{
Align(type.Align);
ReadBits(elemSize);
}
}
break;
case CtfTypes.Float:
CtfFloat flt = (CtfFloat)type;
ReadBits(flt.Exp + flt.Mant);
return 0f; // TODO: Not implemented.
break;
case CtfTypes.Integer:
CtfInteger ctfInt = (CtfInteger)type;
return ReadInteger(ctfInt);
ReadBits(ctfInt.Size);
break;
case CtfTypes.String:
Debug.Assert((_bitOffset % 8) == 0);
int startOffset = _bitOffset >> 3;
int offset = startOffset;
ReadBits(8);
bool ascii = ((CtfString)type).IsAscii;
return ReadString(ascii);
if (ascii)
{
while (_buffer[offset++] != 0)
ReadBits(8);
}
else
{
byte b = _buffer[offset];
while (b != 0)
{
switch (b)
{
default:
break;
case 0xc:
case 0xd:
ReadBits(8);
break;
case 0xe:
ReadBits(16);
break;
case 0xf:
ReadBits(24);
break;
}
offset = ReadBits(8) >> 3;
b = _buffer[offset];
}
}
int bufferLen = (_bitOffset >> 3) - startOffset;
Encoding encoding = ascii ? Encoding.ASCII : Encoding.UTF8;
byte[] newArr = Encoding.Convert(encoding, Encoding.Unicode, _buffer, startOffset, bufferLen);
((CtfString)type).Length = bufferLen;
if (_buffer.Length < _bufferLength + newArr.Length)
{
byte[] buffer = ReallocateBuffer(_bufferLength + newArr.Length);
System.Buffer.BlockCopy(buffer, 0, _buffer, 0, _bufferLength);
}
System.Buffer.BlockCopy(newArr, 0, _buffer, startOffset, newArr.Length);
_bufferLength = startOffset + newArr.Length;
_bitOffset = _bufferLength * 8;
break;
case CtfTypes.Struct:
return ReadStruct((CtfStruct)type);
ReadStruct((CtfStruct)type);
break;
case CtfTypes.Variant:
CtfVariant var = (CtfVariant)type;
int i = strct.GetFieldIndex(var.Switch);
CtfField field = strct.Fields[i];
CtfField field = context.GetField(var.Switch);
CtfEnum enumType = (CtfEnum)field.Type;
int value = strct.GetFieldValue<int>(result, i);
int value = CtfInteger.ReadInt<int>(enumType, _buffer, enumType.BitOffset);
string name = enumType.GetName(value);
field = var.Union.Where(f => f.Name == name).Single();
return ReadType(strct, result, field.Type);
field = var.GetVariant(name);
ReadTypeIntoBuffer(null, field.Type);
break;
default:
throw new InvalidOperationException();
}
}
private object ReadInteger(CtfInteger ctfInt)
{
if (ctfInt.Size > 64)
throw new NotImplementedException();
Align(ctfInt.Align);
int bitOffset = ReadBits(ctfInt.Size);
int byteOffset = bitOffset / 8;
bool fastPath = (_bitOffset % 8) == 0 && (ctfInt.Size % 8) == 0;
if (fastPath)
{
if (ctfInt.Size == 32)
{
if (ctfInt.Signed)
return BitConverter.ToInt32(_buffer, byteOffset);
return BitConverter.ToUInt32(_buffer, byteOffset);
}
if (ctfInt.Size == 8)
{
if (ctfInt.Signed)
return (sbyte)_buffer[byteOffset];
return _buffer[byteOffset];
}
if (ctfInt.Size == 64)
{
if (ctfInt.Signed)
return BitConverter.ToInt64(_buffer, byteOffset);
return BitConverter.ToUInt64(_buffer, byteOffset);
}
Debug.Assert(ctfInt.Size == 16);
if (ctfInt.Signed)
return BitConverter.ToInt16(_buffer, byteOffset);
return BitConverter.ToUInt16(_buffer, byteOffset);
}
// Sloooow path for misaligned integers
int bits = ctfInt.Size;
ulong value = 0;
int byteLen = IntHelpers.AlignUp(bits, 8) / 8;
for (int i = 0; i < byteLen; i++)
value = unchecked((value << 8) | _buffer[byteOffset + byteLen - i - 1]);
value >>= bitOffset;
value &= (ulong)((1 << bits) - 1);
if (ctfInt.Signed)
{
ulong signBit = (1u << (bits - 1));
if ((value & signBit) != 0)
value |= ulong.MaxValue << bits;
}
if (ctfInt.Size > 32)
{
if (ctfInt.Signed)
return (long)value;
return value;
}
if (ctfInt.Size > 16)
{
if (ctfInt.Signed)
return (int)value;
return (uint)value;
}
if (ctfInt.Size > 8)
{
if (ctfInt.Signed)
return (short)value;
return (ushort)value;
}
if (ctfInt.Signed)
return (sbyte)value;
return (byte)value;
}
#region IDisposable
public void Dispose()
{
@@ -475,109 +470,5 @@ namespace Microsoft.Diagnostics.Tracing.Ctf
_eof = true;
}
}
byte[] _stringBuffer = new byte[1024];
internal string ReadString(bool ascii)
{
byte b = ReadByte();
if (b == 0)
{
if (_buffer.Length < _bufferLength + 2)
{
byte[] buffer = ReallocateBuffer(_bufferLength + 2);
System.Buffer.BlockCopy(buffer, 0, _buffer, 0, _bufferLength);
}
_buffer[_bufferLength++] = 0;
_buffer[_bufferLength++] = 0;
_bitOffset += 16;
return "";
}
int i = 0;
_stringBuffer[i++] = b;
if (ascii)
{
while (b != 0)
{
if (i >= _stringBuffer.Length - 4)
{
byte[] tmp = _stringBuffer;
_stringBuffer = new byte[_stringBuffer.Length + 1024];
System.Buffer.BlockCopy(tmp, 0, _stringBuffer, 0, tmp.Length);
}
b = _stringBuffer[i++] = ReadByte();
}
}
else
{
while (b != 0)
{
if (i >= _stringBuffer.Length - 4)
{
byte[] tmp = _stringBuffer;
_stringBuffer = new byte[_stringBuffer.Length + 1024];
System.Buffer.BlockCopy(tmp, 0, _stringBuffer, 0, tmp.Length);
}
b >>= 4;
switch (b)
{
default:
break;
case 0xc:
case 0xd:
_stringBuffer[i++] = ReadByte();
break;
case 0xe:
_stringBuffer[i++] = ReadByte();
_stringBuffer[i++] = ReadByte();
break;
case 0xf:
_stringBuffer[i++] = ReadByte();
_stringBuffer[i++] = ReadByte();
_stringBuffer[i++] = ReadByte();
break;
}
b = _stringBuffer[i++] = ReadByte();
}
}
Encoding encoding = ascii ? Encoding.ASCII : Encoding.UTF8;
string s = encoding.GetString(_stringBuffer, 0, i - 1);
byte[] newArr = Encoding.Convert(encoding, Encoding.Unicode, _stringBuffer, 0, i);
if (_buffer.Length < _bufferLength + newArr.Length)
{
byte[] buffer = ReallocateBuffer(_bufferLength + newArr.Length);
System.Buffer.BlockCopy(buffer, 0, _buffer, 0, _bufferLength);
}
System.Buffer.BlockCopy(newArr, 0, _buffer, _bufferLength, newArr.Length);
_bufferLength += newArr.Length;
_bitOffset += newArr.Length * 8;
return s;
}
private byte ReadByte()
{
int c = _stream.ReadByte();
if (c == -1)
{
_eof = true;
return 0;
}
return (byte)c;
}
}
}
+5 -8
View File
@@ -492,6 +492,9 @@ namespace Microsoft.Diagnostics.Tracing
CtfEvent evt = header.Event;
lastTimestamp = header.Timestamp;
entry.Reader.ReadEventIntoBuffer(evt);
events++;
#if DEBUG
if (_debugOut != null)
{
@@ -499,18 +502,11 @@ namespace Microsoft.Diagnostics.Tracing
_debugOut.WriteLine($" Process: {header.ProcessName}");
_debugOut.WriteLine($" File: {entry.FileName}");
_debugOut.WriteLine($" File Offset: {entry.Channel.FileOffset}");
_debugOut.WriteLine($" Event #{events}");
object[] result = entry.Reader.ReadEvent(evt);
evt.WriteLine(_debugOut, result, 4);
_debugOut.WriteLine($" Event #{events}: {evt.Name}");
}
else
#endif
entry.Reader.ReadEventIntoBuffer(evt);
events++;
ETWMapping etw = GetTraceEvent(evt);
if (etw.IsNull)
continue;
@@ -518,6 +514,7 @@ namespace Microsoft.Diagnostics.Tracing
TraceEvent traceEvent = Lookup(hdr);
traceEvent.eventRecord = hdr;
traceEvent.userData = entry.Reader.BufferPtr;
traceEvent.EventTypeUserData = evt;
traceEvent.DebugValidate();
Dispatch(traceEvent);