Пример #1
0
        private void AssertPathIsCorrect(ClrHeap heap, ClrObject[] path, ulong source, ulong target)
        {
            Assert.NotNull(path);
            Assert.True(path.Length > 0);

            ClrObject first = path.First();

            Assert.Equal(source, first.Address);

            for (int i = 0; i < path.Length - 1; i++)
            {
                ClrObject curr = path[i];
                Assert.Equal(curr.Type, heap.GetObjectType(curr.Address));

                IEnumerable <ClrObject> refs = curr.EnumerateObjectReferences();

                ClrObject next = path[i + 1];
                Assert.Contains(next, refs);
            }

            ClrObject last = path.Last();

            Assert.Equal(last.Type, heap.GetObjectType(last.Address));
            Assert.Equal(target, last.Address);
        }
Пример #2
0
 private static void ShowObject(ClrHeap heap, ClrObject clrObject, string indent)
 {
     Console.WriteLine($"{indent} {clrObject.Type.Name} ({clrObject.HexAddress}) - gen{heap.GetGeneration(clrObject.Address)}");
     foreach (var reference in clrObject.EnumerateObjectReferences())
     {
         ShowObject(heap, reference, "  ");
     }
 }
Пример #3
0
        private void CalculateTypeStatisticsPhase2(ClrHeap heap, Regex typesToReportStatisticsOnRegex, HashSet <ulong> markedObjects, TypeStatistics typeStatistics)
        {
            typeStatistics.MemoryProfilingStopwatch.Start();

            HashSet <ulong>   visitedObjects = new HashSet <ulong>();
            Queue <ClrObject> objectQueue    = new Queue <ClrObject>();

            // Start with exclusive = inclusive and walk the heap from roots looking for objects to subtract from this number.
            typeStatistics.ExclusiveRetainedBytes = typeStatistics.InclusiveRetainedBytes;

            foreach (ClrRoot root in heap.EnumerateRoots())
            {
                // Interested only in roots outside of our marked inclusive graph.
                if (!markedObjects.Contains(root.Object))
                {
                    ClrObject rootObj = heap.GetObject(root.Object);
                    objectQueue.Enqueue(rootObj);
                    visitedObjects.Add(root.Object);

                    while (objectQueue.Count > 0)
                    {
                        ClrObject obj = objectQueue.Dequeue();
                        if (obj.IsNull || obj.Type == null)
                        {
                            continue;
                        }

                        // We stop the walk when we see an object of a type we are reporting statistics on.
                        if (!typesToReportStatisticsOnRegex.IsMatch(obj.Type.Name))
                        {
                            if (markedObjects.Contains(obj.Address))
                            {
                                // Not an object of a type we are reporting statistics on but it is part of the inclusive object graph.
                                // This means that it must not be reported in the exclusive bytes.
                                typeStatistics.ExclusiveRetainedBytes -= obj.Size;
                                markedObjects.Remove(obj.Address);
                            }

                            // Follow all references.
                            foreach (var reference in obj.EnumerateObjectReferences())
                            {
                                if (!reference.IsNull && !visitedObjects.Contains(reference.Address))
                                {
                                    visitedObjects.Add(reference.Address);
                                    objectQueue.Enqueue(reference);
                                }
                            }
                        }
                    }
                }
            }

            typeStatistics.MemoryProfilingStopwatch.Stop();
        }
Пример #4
0
        public void EnumerateGCRefsArray()
        {
            using DataTarget dataTarget = TestTargets.GCRoot.LoadFullDump();
            ClrRuntime runtime = dataTarget.ClrVersions.Single().CreateRuntime();
            ClrHeap    heap    = runtime.Heap;

            ClrModule module   = heap.Runtime.GetMainModule();
            ClrType   mainType = module.GetTypeByName("GCRootTarget");

            ClrObject obj = mainType.GetStaticObjectValue("TheRoot");

            obj = obj.GetObjectField("Item1");

            Assert.Equal("System.Object[]", obj.Type.Name);

            ClrObject[] refs = obj.EnumerateObjectReferences(false).ToArray();
            Assert.Single(refs);
            Assert.Equal("DoubleRef", refs[0].Type.Name);
        }
Пример #5
0
        /// <summary>
        /// Enumerates all objects reachable from GC roots in the given heap. Each object is returned exactly once.
        /// </summary>
        private IEnumerable <ClrObject> EnumerateRootedObjects(ClrHeap heap)
        {
            HashSet <ulong>   visitedObjects = new HashSet <ulong>();
            Queue <ClrObject> objectQueue    = new Queue <ClrObject>();

            foreach (ClrRoot root in heap.EnumerateRoots())
            {
                if (!visitedObjects.Contains(root.Object))
                {
                    ClrObject rootObj = heap.GetObject(root.Object);
                    objectQueue.Enqueue(rootObj);
                    visitedObjects.Add(root.Object);
                    if (rootObj.Type != null)
                    {
                        yield return(rootObj);
                    }

                    while (objectQueue.Count > 0)
                    {
                        ClrObject obj = objectQueue.Dequeue();
                        if (obj.IsNull || obj.Type == null)
                        {
                            continue;
                        }
                        // Follow all references.
                        foreach (var reference in obj.EnumerateObjectReferences())
                        {
                            if (!reference.IsNull && !visitedObjects.Contains(reference.Address))
                            {
                                objectQueue.Enqueue(reference);
                                visitedObjects.Add(reference.Address);
                                yield return(reference);
                            }
                        }
                    }
                }
            }
        }
Пример #6
0
        private void CalculateTypeStatisticsPhase1(ClrObject rootObj, Regex typesToReportStatisticsOnRegex, HashSet <ulong> markedObjects, TypeStatistics typeStatistics)
        {
            if (!markedObjects.Contains(rootObj.Address))
            {
                // Start the stopwatch only if we're looking at an unmarked object. Measuring the single HashSet.Contains() would have more
                // overhead than the actual duration of the operation.
                typeStatistics.MemoryProfilingStopwatch.Start();

                Queue <ClrObject> objectQueue = new Queue <ClrObject>();
                objectQueue.Enqueue(rootObj);
                markedObjects.Add(rootObj.Address);

                while (objectQueue.Count > 0)
                {
                    ClrObject obj = objectQueue.Dequeue();
                    typeStatistics.InclusiveRetainedBytes += obj.Size;

                    foreach (var reference in obj.EnumerateObjectReferences())
                    {
                        if (!reference.IsNull && !markedObjects.Contains(reference.Address))
                        {
                            // We follow references only as long as they point to BCL types or to types to report statistics on.
                            // Otherwise we would transitively walk pretty much the entire managed heap and the number we report
                            // would be meaningless.
                            string referenceType = reference.Type.Name;
                            if (referenceType.StartsWith("System.") || typesToReportStatisticsOnRegex.IsMatch(referenceType))
                            {
                                markedObjects.Add(reference.Address);
                                objectQueue.Enqueue(reference);
                            }
                        }
                    }
                }

                typeStatistics.MemoryProfilingStopwatch.Stop();
            }
        }
Пример #7
0
 /// <summary>
 ///     Enumerates all objects that this object references.
 /// </summary>
 /// <param name="carefully">if set to <c>true</c> [carefully].</param>
 /// <returns>An enumeration of object references.</returns>
 /// <inheritdoc />
 public IEnumerable <IClrObject> EnumerateObjectReferences(bool carefully = false) =>
 Object.EnumerateObjectReferences(carefully).Select(Converter.Convert);