Example #1
0
        static void Main(string[] args)
        {
            // build a "class histogram" (i.e. !dumpheap -stat in WinDBG+sos)
            // in an optimized way
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions[0].CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                var statistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int objectCount = 0;

                // build the class histogram: count and cumulated size of instances per type
                foreach (var objDetails in heap.EnumerateObjectDetails())
                {
                    ulong   address = objDetails.Item1;
                    ulong   mt      = objDetails.Item2;
                    ClrType type    = objDetails.Item3;
                    ulong   size    = objDetails.Item4;

                    TypeEntry entry;
                    if (!statistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName    = type.Name,
                            MethodTable = mt,
                            Size        = 0
                        };
                        statistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    objectCount++;
                }

                // display a la !dumpheap -stat
                var sortedStatistics =
                    from entry in statistics.Values
                    orderby entry.Size
                    select entry;
                Console.WriteLine("{0,12} {1,12} {2,12} {3}", "MT", "Count", "TotalSize", "Class Name");
                foreach (var entry in sortedStatistics)
                {
                    Console.WriteLine($"{entry.MethodTable,12:X12} {entry.Size,12:D} {entry.Count,12:D} {entry.TypeName}");
                }
                Console.WriteLine($"Total {objectCount} objects");
            }
        }
Example #2
0
        public void OptimizedClassHistogram()
        {
            using (DataTarget dt = TestTargets.Types.LoadFullDump())
            {
                ClrRuntime runtime = dt.ClrVersions.Single().CreateRuntime();
                ClrHeap    heap    = runtime.Heap;

                // ensure that the optimized version is faster than the default one
                Stopwatch timing = new Stopwatch();
                var       notOptimizedStatistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int       notOptimizedObjectCount = 0;

                // with an optimized version
                timing.Start();

                foreach (var objDetails in heap.EnumerateObjectDetails())
                {
                    ClrType type = objDetails.Item3;
                    ulong   size = objDetails.Item4;

                    TypeEntry entry;
                    if (!notOptimizedStatistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        notOptimizedStatistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    notOptimizedObjectCount++;
                }

                timing.Stop();
                var notOptimizedTime = TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds);


                // with an non-optimized version
                var statistics  = new Dictionary <ClrType, TypeEntry>(32768);
                int objectCount = 0;
                timing.Restart();

                foreach (ulong objAddress in heap.EnumerateObjectAddresses())
                {
                    ClrType type = heap.GetObjectType(objAddress);
                    ulong   size = type.GetSize(objAddress);

                    TypeEntry entry;
                    if (!statistics.TryGetValue(type, out entry))
                    {
                        entry = new TypeEntry()
                        {
                            TypeName = type.Name,
                            Size     = 0
                        };
                        statistics[type] = entry;
                    }
                    entry.Count++;
                    entry.Size += size;
                    objectCount++;
                }

                timing.Stop();

                // check object count
                Assert.AreEqual(notOptimizedObjectCount, objectCount);

                // check heap content
                var types = notOptimizedStatistics.Keys;
                foreach (var type in types)
                {
                    var notOptimizedDetails = notOptimizedStatistics[type];
                    var details             = statistics[type];

                    Assert.AreEqual(notOptimizedDetails.TypeName, details.TypeName);
                    Assert.AreEqual(notOptimizedDetails.Count, details.Count);
                    Assert.AreEqual(notOptimizedDetails.Size, details.Size);
                }
                Assert.AreEqual(types.Count, statistics.Count);

                // checking that optimized is faster could be flaky
                // Assert.IsTrue(notOptimizedTime > TimeSpan.FromMilliseconds(timing.ElapsedMilliseconds));
            }
        }