private static IEnumerable <Tuple <ulong, ClrType> > EnumerateFromObjectSet(ClrHeap heap, IEnumerable <ulong> objects) { var toGoThrough = new Stack <ulong>(objects); var seen = new ObjectSet(heap); while (toGoThrough.Count > 0) { var obj = toGoThrough.Pop(); if (seen.Contains(obj)) { continue; } seen.Add(obj); var type = heap.GetObjectType(obj); if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name)) { continue; } yield return(new Tuple <ulong, ClrType>(obj, type)); type.EnumerateRefsOfObject(obj, (child, _) => { if (child != 0 && !seen.Contains(child)) { toGoThrough.Push(child); } }); } }
private void BuildChunkIndex() { var seen = new ObjectSet(_heap); var evalStack = new Stack<ulong>(); foreach (var root in _heap.EnumerateRoots(enumerateStatics: false)) { evalStack.Push(root.Object); _directlyRooted.Add(root.Object); } while (evalStack.Count > 0) { ulong parent = evalStack.Pop(); if (seen.Contains(parent)) continue; seen.Add(parent); var type = _heap.GetObjectType(parent); if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name)) continue; type.EnumerateRefsOfObject(parent, (child, _) => { // Due to possibly a corruption or a bug in ClrMD, the inner fields might // occasionally fall outside of the heap, or point to objects whose type // cannot be obtained. We don't have a choice but to ignore these. if (_heap.GetObjectType(child) == null) return; int childChunk = ChunkIdForObject(child); int parentChunk = ChunkIdForObject(parent); HashSet<int> referencingChunks; if (!_tempChunkToReferencingChunks.TryGetValue(childChunk, out referencingChunks)) { referencingChunks = new HashSet<int>(); _tempChunkToReferencingChunks.Add(childChunk, referencingChunks); } referencingChunks.Add(parentChunk); if (child != 0 && !seen.Contains(child)) { evalStack.Push(child); } }); } _context.WriteLine("Average referencing chunks per chunk: {0:N}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Average()); _context.WriteLine("Max referencing chunks per chunk: {0}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Max()); _context.WriteLine("Min referencing chunks per chunk: {0}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Min()); _context.WriteLine("Objects with missing chunk ids: {0}", _objectsWithMissingChunkIds); // Convert to a more compact representation for in-memory use and serialization. foreach (var kvp in _tempChunkToReferencingChunks) { _chunkToReferencingChunks.Add(kvp.Key, kvp.Value.ToArray()); } _tempChunkToReferencingChunks.Clear(); }
private static IEnumerable<Tuple<ulong, ClrType>> EnumerateFromObjectSet(ClrHeap heap, IEnumerable<ulong> objects) { var toGoThrough = new Stack<ulong>(objects); var seen = new ObjectSet(heap); while (toGoThrough.Count > 0) { var obj = toGoThrough.Pop(); if (seen.Contains(obj)) continue; seen.Add(obj); var type = heap.GetObjectType(obj); if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name)) continue; yield return new Tuple<ulong, ClrType>(obj, type); type.EnumerateRefsOfObject(obj, (child, _) => { if (child != 0 && !seen.Contains(child)) { toGoThrough.Push(child); } }); } }
private void BuildChunkIndex() { var seen = new ObjectSet(_heap); var evalStack = new Stack <ulong>(); foreach (var root in _heap.EnumerateRoots(enumerateStatics: false)) { evalStack.Push(root.Object); _directlyRooted.Add(root.Object); } while (evalStack.Count > 0) { ulong parent = evalStack.Pop(); if (seen.Contains(parent)) { continue; } seen.Add(parent); var type = _heap.GetObjectType(parent); if (type == null || type.IsFree || String.IsNullOrEmpty(type.Name)) { continue; } type.EnumerateRefsOfObject(parent, (child, _) => { // Due to possibly a corruption or a bug in ClrMD, the inner fields might // occasionally fall outside of the heap, or point to objects whose type // cannot be obtained. We don't have a choice but to ignore these. if (_heap.GetObjectType(child) == null) { return; } int childChunk = ChunkIdForObject(child); int parentChunk = ChunkIdForObject(parent); HashSet <int> referencingChunks; if (!_tempChunkToReferencingChunks.TryGetValue(childChunk, out referencingChunks)) { referencingChunks = new HashSet <int>(); _tempChunkToReferencingChunks.Add(childChunk, referencingChunks); } referencingChunks.Add(parentChunk); if (child != 0 && !seen.Contains(child)) { evalStack.Push(child); } }); } _context.WriteLine("Average referencing chunks per chunk: {0:N}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Average()); _context.WriteLine("Max referencing chunks per chunk: {0}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Max()); _context.WriteLine("Min referencing chunks per chunk: {0}", (from list in _tempChunkToReferencingChunks.Values select list.Count).Min()); _context.WriteLine("Objects with missing chunk ids: {0}", _objectsWithMissingChunkIds); // Convert to a more compact representation for in-memory use and serialization. foreach (var kvp in _tempChunkToReferencingChunks) { _chunkToReferencingChunks.Add(kvp.Key, kvp.Value.ToArray()); } _tempChunkToReferencingChunks.Clear(); }