internal void RecordGc(int tickIndex, SampleObjectTable sampleObjectTable, bool simpleForm) { if (simpleForm && nullRelocationsSeen || newLiveRoot != null) { // in this case assume anything not reported is dead updateRoot = SortIntervals(updateRoot); ulong prevHiAddr = 0; for (Interval i = updateRoot; i != null; i = i.next) { if (prevHiAddr < i.loAddr) { RemoveRange(prevHiAddr, i.loAddr, tickIndex, sampleObjectTable); } if (prevHiAddr < i.hiAddr) prevHiAddr = i.hiAddr; } RemoveRange(prevHiAddr, ulong.MaxValue, tickIndex, sampleObjectTable); updateRoot = null; if (newLiveRoot != null) { liveRoot = newLiveRoot; newLiveRoot = null; } } else { for (Interval i = liveRoot; i != null; i = i.next) i.justHadGc = true; } nullRelocationsSeen = false; }
internal bool AddObject(ulong id, uint size, int allocTickIndex, SampleObjectTable sampleObjectTable) { size = (size + 3) & (uint.MaxValue - 3); Interval prevInterval = null; Interval bestInterval = null; Interval prevI = null; bool emptySpace = false; // look for the best interval to put this object in. for (Interval i = liveRoot; i != null; i = i.next) { if (i.loAddr < id + size && id <= i.hiAddr + allowableGap) { if (bestInterval == null || bestInterval.loAddr < i.loAddr) { bestInterval = i; prevInterval = prevI; } } prevI = i; } if (bestInterval != null) { if (bestInterval.loAddr > id) { bestInterval.loAddr = id; } if (id < bestInterval.hiAddr) { if (bestInterval.hadRelocations && bestInterval.justHadGc) { // Interval gets shortened liveObjectTable.RemoveObjectRange(id, bestInterval.hiAddr - id, allocTickIndex, sampleObjectTable); bestInterval.hiAddr = id + size; bestInterval.justHadGc = false; } } else { bestInterval.hiAddr = id + size; emptySpace = true; } if (prevInterval != null) { // Move to front to speed up future searches. prevInterval.next = bestInterval.next; bestInterval.next = liveRoot; liveRoot = bestInterval; } if (OverlappingInterval(bestInterval) != null) MergeInterval(bestInterval); return emptySpace; } liveRoot = new Interval(id, id + size, -1, liveRoot); //Debug.Assert(OverlappingInterval(liveRoot) == null); return emptySpace; }
private void RemoveRange(ulong loAddr, ulong hiAddr, int tickIndex, SampleObjectTable sampleObjectTable) { Interval next; for (Interval i = liveRoot; i != null; i = next) { next = i.next; ulong lo = Math.Max(loAddr, i.loAddr); ulong hi = Math.Min(hiAddr, i.hiAddr); if (lo >= hi) continue; liveObjectTable.RemoveObjectRange(lo, hi - lo, tickIndex, sampleObjectTable); if (i.hiAddr == hi) { if (i.loAddr == lo) DeleteInterval(i); else i.hiAddr = lo; } } }
internal void RecordGc(int tickIndex, int gcGen0Count, int gcGen1Count, int gcGen2Count, SampleObjectTable sampleObjectTable) { int gen = 0; if (gcGen2Count != lastGcGen2Count) gen = 2; else if (gcGen1Count != lastGcGen1Count) gen = 1; RecordGc(tickIndex, gen, sampleObjectTable, false); lastGcGen0Count = gcGen0Count; lastGcGen1Count = gcGen1Count; lastGcGen2Count = gcGen2Count; }
internal void RecordGc(int tickIndex, int gen, SampleObjectTable sampleObjectTable, bool simpleForm) { lastTickIndex = tickIndex; if (sampleObjectTable != null) sampleObjectTable.AddGcTick(tickIndex, gen); intervalTable.RecordGc(tickIndex, sampleObjectTable, simpleForm); if (gen >= 1) gen2LimitTickIndex = gen1LimitTickIndex; gen1LimitTickIndex = tickIndex; lastGcGen0Count++; if (gen > 0) { lastGcGen1Count++; if (gen > 1) lastGcGen2Count++; } }
internal void UpdateObjects(Histogram relocatedHistogram, ulong oldId, ulong newId, uint length, int tickIndex, SampleObjectTable sampleObjectTable) { if (lastPos >= readNewLog.pos) return; lastPos = readNewLog.pos; lastTickIndex = tickIndex; intervalTable.Relocate(oldId, newId, length); if (oldId == newId) return; ulong nextId; ulong lastId = oldId + length; LiveObject o; for (GetNextObject(oldId, lastId, out o); o.id < lastId; GetNextObject(nextId, lastId, out o)) { nextId = o.id + o.size; ulong offset = o.id - oldId; if (sampleObjectTable != null) sampleObjectTable.Delete(o.id, o.id + o.size, tickIndex); Zero(o.id, o.size); InsertObject(newId + offset, o.typeSizeStacktraceIndex, o.allocTickIndex, tickIndex, false, sampleObjectTable); if (relocatedHistogram != null) relocatedHistogram.AddObject(o.typeSizeStacktraceIndex, 1); } }
void RemoveObjectRange(ulong firstId, ulong length, int tickIndex, SampleObjectTable sampleObjectTable) { ulong lastId = firstId + length; if (sampleObjectTable != null) sampleObjectTable.Delete(firstId, lastId, tickIndex); Zero(firstId, length); }
internal void InsertObject(ulong id, int typeSizeStacktraceIndex, int allocTickIndex, int nowTickIndex, bool newAlloc, SampleObjectTable sampleObjectTable) { if (lastPos >= readNewLog.pos && newAlloc) return; lastPos = readNewLog.pos; lastTickIndex = nowTickIndex; int[] stacktrace = readNewLog.stacktraceTable.IndexToStacktrace(typeSizeStacktraceIndex); int typeIndex = stacktrace[0]; uint size = (uint)stacktrace[1]; bool emptySpace = false; if (newAlloc) { emptySpace = intervalTable.AddObject(id, size, allocTickIndex, sampleObjectTable); } if (!emptySpace) { ulong prevId = FindObjectBackward(id - 4); LiveObject o; GetNextObject(prevId, id, out o); if (o.id < id && (o.id + o.size > id || o.id + 12 > id)) { Zero(o.id, id - o.id); } } //Debug.Assert(FindObjectBackward(id - 4) + 12 <= id); if (size >= 12) { ushort u1 = (ushort)(typeSizeStacktraceIndex | 0x8000); ushort u2 = (ushort)((typeSizeStacktraceIndex >> 15) | ((allocTickIndex & 0xff) << 7)); ushort u3 = (ushort)(allocTickIndex >> 8); Write3WordsAt(id, u1, u2, u3); if (!emptySpace) Zero(id + 12, size - 12); //Debug.Assert(CanReadObjectBackCorrectly(id, size, typeSizeStacktraceIndex, allocTickIndex)); } if (sampleObjectTable != null) sampleObjectTable.Insert(id, id + size, nowTickIndex, allocTickIndex, typeIndex); }