public GCSimulation(ClrProfilerParser profiler) { m_clrProfiler = profiler; m_relocs = new GrowableArray <Relocation>(256); Allocs = new GrowableArray <AllocInfo>(100000); m_clrProfiler.GCStart += new ClrProfilerParser.GCEventHandler(this.GCStart); m_clrProfiler.GCEnd += new ClrProfilerParser.GCEventHandler(this.GCEnd); m_clrProfiler.ObjectRangeLive += new ClrProfilerParser.LiveObjectRangeHandler(this.ObjectRangeLive); m_clrProfiler.ObjectRangeRelocation += new ClrProfilerParser.RelocationEventHandler(this.ObjectRangeRelocation); // TODO expose the thread information AllocInfo info = new AllocInfo(); m_clrProfiler.Allocation += delegate(ProfilerAllocID allocId, Address objectAddress, uint threadId) { Debug.Assert(allocId != ProfilerAllocID.Null); info.Size = (int)m_clrProfiler.GetAllocSize(allocId); info.AllocId = allocId; var stackId = m_clrProfiler.GetAllocStack(allocId); info.MsecFromStart = CurrentTimeMSec; info.ObjectAddress = objectAddress; Allocs.Add(info); m_numAllocs++; }; m_clrProfiler.Tick += delegate(int milliSecondsSinceStart) { CurrentTimeMSec = milliSecondsSinceStart; }; }
// Returns true if 'alloc' survivies. private bool ApplyRelocsToAlloc(ref AllocInfo alloc) { // You survive if your generation is large than the condemed generation. if (alloc.Generation > m_condemedGeneration) { return(true); } Debug.Assert(m_areRelocsSorted); // See if you survived. int idx = m_lastRelocIdx; // See if you can start where you left off. if (alloc.ObjectAddress < m_lastRelocRegionEnd) { idx = 0; // Nope, start at the begining. } while (idx < m_relocs.Count) { if (alloc.ObjectAddress < m_relocs[idx].SourceStart) { return(false); } if (alloc.ObjectAddress < m_relocs[idx].SourceEnd) { alloc.ObjectAddress = alloc.ObjectAddress + m_relocs[idx].DiffToTarget; alloc.Generation = m_promotedToGeneration; return(true); } m_lastRelocRegionEnd = m_relocs[idx].SourceEnd; idx++; m_lastRelocIdx = idx; } // TODO FIX NOW, not right when we have segments everywhere.. // OK it did not survive the condemed generation, see if it is in a segment that was not condemed if (m_condemedGeneration < 2) { foreach (var gcSegment in m_gcSegments) { if (gcSegment.rangeStart <= alloc.ObjectAddress && alloc.ObjectAddress < gcSegment.rangeStart + (ulong)gcSegment.rangeLength) { // Note rangeGeneration can == 3 for Large object heap, but this still works because we only even look // for generations less than 2. return(gcSegment.rangeGeneration > m_condemedGeneration); } } Debug.Assert(false, "Object in no heap segment!"); } return(false); }