private void AddProfilerEvent(Event @event) { string eventType = (@event.EventType == EventType.GarbageCollectionFinished) ? "GC" : "JIT"; _parent.DebugWrite(String.Format("#{0} {1} (start={2}ms; end={3}ms)", ++_dbgIdx, eventType, _startMilliseconds, @event.TimeMilliseconds)); double startSeconds = _startMilliseconds / 1000.0; double endSeconds = @event.TimeMilliseconds / 1000.0; lock (_pendingJobItemsGuard) { if (_pendingJobItems == null) { _pendingJobItems = new List <ClrJobItem>(); } else { int count = _pendingJobItems.Count; // > 0 if pendingJobItems is not null ClrJobItem lastEnd = _pendingJobItems[count - 1]; if (endSeconds <= lastEnd.TimeSeconds) { _parent.DebugWrite(String.Format("#{0} Ignored (1)", _dbgIdx)); return; // ignore duplicate or obsolete events } if (startSeconds <= lastEnd.TimeSeconds) // intersecting events { if (endSeconds <= lastEnd.TimeSeconds) { _parent.DebugWrite(String.Format("#{0} Ignored (2)", _dbgIdx)); return; } // special: merge events _pendingJobItems.RemoveAt(count - 1); _pendingJobItems.Add(new ClrJobItem(endSeconds, false)); _parent.DebugWrite(String.Format( "#{0} Replaced last {1} from (start={2:F3}s; end={3:F3}s) to (start={4:F3}s; end={5:F3}s)", _dbgIdx, eventType, _pendingJobItems[count - 2].TimeSeconds, lastEnd.TimeSeconds, _pendingJobItems[count - 2].TimeSeconds, endSeconds)); return; } } _pendingJobItems.Add(new ClrJobItem(startSeconds, true)); if (startSeconds == endSeconds) { const double MinTimeDelta = 0.001; // 1 msec endSeconds += MinTimeDelta; } _pendingJobItems.Add(new ClrJobItem(endSeconds, false)); } _parent.DebugWrite(String.Format("#{0} Added {1} (start={2:F3}s; end={3:F3}s)", _dbgIdx, eventType, startSeconds, endSeconds)); }
private static void WriteClrJobItems(StreamWriter writer, IList <ClrJobItem> items) { ClrJobItem jobStart = null; int n = 0; for (int i = 0, count = items.Count; i < count; ++i) { ClrJobItem job = items[i]; if (i % 2 == 0) { if (!job.IsStart) { writer.WriteLine($"WARNING: unexpected end item ({job.TimeSeconds:F3})"); continue; } jobStart = job; } else { if (job.IsStart) { writer.WriteLine($"WARNING: unexpected start item ({job.TimeSeconds:F3})"); continue; } if (jobStart == null) { writer.WriteLine($"WARNING: end item without start item ({job.TimeSeconds:F3})"); continue; } writer.WriteLine($"#{++n:D4} {jobStart.TimeSeconds:F3} .. {job.TimeSeconds:F3}"); jobStart = null; } } if (jobStart != null) { writer.WriteLine($"WARNING: start item without end item ({jobStart.TimeSeconds:F3})"); } }
// adds new items to chart values; may need to combine the end of the existing chart values and // the beginning of the new items list private void AddClrJobItems(ChartValues <ClrJobItem> chartValues, List <ClrJobItem> jobItems, string eventTypeName) { Debug.Assert((jobItems.Count >= 2) && (jobItems.Count % 2 == 0)); int chartValuesCount = chartValues.Count; if (chartValuesCount > 0) { Debug.Assert((chartValuesCount >= 2) && chartValues[chartValuesCount - 2].IsStart && !chartValues[chartValuesCount - 1].IsStart); double lastOldItemStartTime = chartValues[chartValuesCount - 2].TimeSeconds; double lastOldItemEndTime = chartValues[chartValuesCount - 1].TimeSeconds; Debug.Assert(lastOldItemStartTime <= lastOldItemEndTime); Debug.Assert(jobItems[0].IsStart && !jobItems[1].IsStart); double firstNewItemStartTime = jobItems[0].TimeSeconds; double firstNewItemEndTime = jobItems[1].TimeSeconds; Debug.Assert(firstNewItemStartTime <= firstNewItemEndTime); if (firstNewItemStartTime <= lastOldItemEndTime) { // intersecting with previous event if (firstNewItemEndTime <= lastOldItemEndTime) { // ignore duplicate events if (firstNewItemStartTime >= lastOldItemStartTime) { jobItems.RemoveRange(0, 2); DebugWrite($"Ignored duplicate {eventTypeName} event {firstNewItemStartTime:F3} .. {firstNewItemEndTime:F3}"); } // else: (unexpected) the next event start is before the previous event start } else // firstNewItemEndTime > lastOldItemEndTime { // combine events if (firstNewItemStartTime >= lastOldItemStartTime) { ClrJobItem saved = chartValues[chartValuesCount - 1]; saved.TimeSeconds = firstNewItemEndTime; chartValues[chartValuesCount - 1] = saved; // allow 'chartValues' to notify it has been changed jobItems.RemoveRange(0, 2); DebugWrite($"Changed last {eventTypeName} event end time to {firstNewItemEndTime:F3}"); } // else: unsupported case } } } if (jobItems.Count > 0) // jobItems might be changed (first two items removed) { chartValues.AddRange(jobItems); DebugWrite($"{jobItems.Count} {eventTypeName} events added to chart"); } }