-
Notifications
You must be signed in to change notification settings - Fork 256
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
186 additions
and
1 deletion.
There are no files selected for viewing
127 changes: 127 additions & 0 deletions
127
src/benchmarks/gc/GC.Infrastructure/GC.Analysis.API/DynamicEvents/DynamicEvents.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
// TODO, AndrewAu, remove this condition when new TraceEvent is available through Nuget. | ||
#if CUSTOM_TRACE_EVENT | ||
|
||
using Microsoft.Diagnostics.Tracing.Analysis.GC; | ||
using Microsoft.Diagnostics.Tracing.Parsers.GCDynamic; | ||
using System.Diagnostics; | ||
using System.Dynamic; | ||
|
||
namespace GC.Analysis.API.DynamicEvents | ||
{ | ||
|
||
public static class TraceGCExtensions | ||
{ | ||
public static dynamic DynamicEvents(this TraceGC traceGC) | ||
{ | ||
return new DynamicIndex(traceGC.DynamicEvents); | ||
} | ||
} | ||
|
||
// TODO, AndrewAu, this could be compiled for better performance, right now we are doing linear lookups | ||
// We can do validation so that the input make sense (i.e. no unexpected types, no duplicate event/field), etc | ||
// | ||
public class DynamicEventSchema | ||
{ | ||
internal static List<DynamicEventSchema> DynamicEventSchemas = new List<DynamicEventSchema>(); | ||
|
||
public string DynamicEventName { get; set; } | ||
|
||
public List<KeyValuePair<string, Type>> Fields { get; set; } | ||
|
||
public static void Set(List<DynamicEventSchema> dynamicEventSchemas) | ||
{ | ||
DynamicEventSchemas = dynamicEventSchemas; | ||
} | ||
} | ||
|
||
internal class DynamicIndex : DynamicObject | ||
{ | ||
private List<DynamicEvent> index; | ||
|
||
public DynamicIndex(List<DynamicEvent> index) | ||
{ | ||
this.index = index; | ||
} | ||
|
||
public override bool TryGetMember(GetMemberBinder binder, out object result) | ||
{ | ||
if (DynamicEventSchema.DynamicEventSchemas.Any(s => string.Equals(s.DynamicEventName, binder.Name))) | ||
{ | ||
string name = binder.Name; | ||
// TODO, andrewau, handle the case where we have multiple dynamic event of the same name in a single GC. | ||
// | ||
// That should be an array of these dynamic events | ||
// Somewhere the schema should tell us if this is expected or not so not to generate wrong stuff just because the data is corrupted. | ||
// | ||
result = new DynamicEventObject(index.Single(r => string.Equals(r.Name, binder.Name)), DynamicEventSchema.DynamicEventSchemas.Single(s => string.Equals(s.DynamicEventName, binder.Name)).Fields); | ||
return true; | ||
} | ||
else | ||
{ | ||
result = null; | ||
return false; | ||
} | ||
} | ||
} | ||
|
||
internal class DynamicEventObject : DynamicObject | ||
{ | ||
private DynamicEvent dynamicEvent; | ||
private Dictionary<string, object> fieldValues; | ||
|
||
public DynamicEventObject(DynamicEvent dynamicEvent, List<KeyValuePair<string, Type>> fields) | ||
{ | ||
this.dynamicEvent = dynamicEvent; | ||
this.fieldValues = new Dictionary<string, object>(); | ||
int offset = 0; | ||
foreach (KeyValuePair<string, Type> field in fields) | ||
{ | ||
object value = null; | ||
// TODO, AndrewAu, all types that we envision this will be needed | ||
if (field.Value == typeof(ushort)) | ||
{ | ||
value = BitConverter.ToUInt16(dynamicEvent.Payload, offset); | ||
offset += 2; | ||
} | ||
else if (field.Value == typeof(ulong)) | ||
{ | ||
value = BitConverter.ToUInt64(dynamicEvent.Payload, offset); | ||
offset += 8; | ||
} | ||
else | ||
{ | ||
Debug.Fail("Unknown field type"); | ||
} | ||
this.fieldValues.Add(field.Key, value); | ||
} | ||
} | ||
|
||
public override bool TryGetMember(GetMemberBinder binder, out object result) | ||
{ | ||
string name = binder.Name; | ||
if (string.Equals(name, "TimeStamp")) | ||
{ | ||
result = this.dynamicEvent.TimeStamp; | ||
return true; | ||
} | ||
else | ||
if (this.fieldValues.TryGetValue(name, out var fieldValue)) | ||
{ | ||
result = fieldValue; | ||
return true; | ||
} | ||
else | ||
{ | ||
result = null; | ||
return false; | ||
} | ||
} | ||
|
||
public override string ToString() | ||
{ | ||
return "I am " + this.dynamicEvent.Name + " with these fields: \n" + string.Join("\n", this.fieldValues.Select(kvp => kvp.Key + "->" + kvp.Value)); | ||
} | ||
} | ||
} | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters