Skip to content

Commit 09a9068

Browse files
committed
Write leaked types to file + write summary of types by count too
1 parent e12080e commit 09a9068

File tree

1 file changed

+31
-10
lines changed

1 file changed

+31
-10
lines changed

UnityMemorySnapshotThing/Program.cs

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
using System.Runtime;
1+
using System.Text;
22
using UMS.Analysis;
3-
using UMS.Analysis.Structures;
43
using UMS.Analysis.Structures.Objects;
5-
using UMS.LowLevel;
6-
using UMS.LowLevel.Structures;
74

85
namespace UnityMemorySnapshotThing;
96

@@ -71,17 +68,23 @@ private static void FindLeakedUnityObjects(SnapshotFile file)
7168
//Find all the managed objects, filter to those which have a m_CachedObjectPtr field
7269
//Then filter to those for which that field is 0 (i.e. not pointing to a native object)
7370
//That gives the leaked managed shells.
74-
Console.WriteLine($"Snapshot contains {file.AllManagedClassInstances.Count()} managed objects");
71+
var ret = new StringBuilder();
72+
var str = $"Snapshot contains {file.AllManagedClassInstances.Count()} managed objects";
73+
Console.WriteLine(str);
74+
ret.AppendLine(str);
7575

7676
var filterStart = DateTime.Now;
7777

7878
var unityEngineObjects = file.AllManagedClassInstances.Where(i => i.InheritsFromUnityEngineObject(file)).ToArray();
79-
80-
Console.WriteLine($"Of those, {unityEngineObjects.Length} inherit from UnityEngine.Object (filtered in {(DateTime.Now - filterStart).TotalMilliseconds} ms)");
79+
80+
str = $"Of those, {unityEngineObjects.Length} inherit from UnityEngine.Object (filtered in {(DateTime.Now - filterStart).TotalMilliseconds} ms)";
81+
Console.WriteLine(str);
82+
ret.AppendLine(str);
8183

8284
var detectStart = DateTime.Now;
8385

8486
int numLeaked = 0;
87+
var leakedTypes = new Dictionary<string, int>();
8588
foreach (var managedClassInstance in unityEngineObjects)
8689
{
8790
var fields = file.GetInstanceFieldInfoForTypeIndex(managedClassInstance.TypeInfo.TypeIndex);
@@ -100,14 +103,32 @@ private static void FindLeakedUnityObjects(SnapshotFile file)
100103
if (integerFieldValue.Value == 0)
101104
{
102105
var typeName = file.GetTypeName(managedClassInstance.TypeInfo.TypeIndex);
103-
Console.WriteLine($"Found leaked managed object of type: {typeName} at memory address 0x{managedClassInstance.ObjectAddress:X}");
104-
Console.WriteLine($" Retention Path: {managedClassInstance.GetFirstObservedRetentionPath(file)}");
106+
107+
str = $"Found leaked managed object of type: {typeName} at memory address 0x{managedClassInstance.ObjectAddress:X}";
108+
Console.WriteLine(str);
109+
ret.AppendLine(str);
110+
111+
str = $" Retention Path: {managedClassInstance.GetFirstObservedRetentionPath(file)}";
112+
Console.WriteLine(str);
113+
ret.AppendLine(str);
114+
115+
leakedTypes[typeName] = leakedTypes.GetValueOrDefault(typeName) + 1;
116+
105117
numLeaked++;
106118
}
107119
}
108120
}
109121
}
122+
123+
str = $"Finished detection in {(DateTime.Now - detectStart).TotalMilliseconds} ms. {numLeaked} of those are leaked managed shells";
124+
Console.WriteLine(str);
125+
ret.AppendLine(str);
126+
127+
var leakedTypesSorted = leakedTypes.OrderByDescending(kvp => kvp.Value).ToArray();
128+
129+
str = $"Leaked types by count: \n{string.Join("\n", leakedTypesSorted.Select(kvp => $"{kvp.Value} x {kvp.Key}"))}";
130+
ret.AppendLine(str);
110131

111-
Console.WriteLine($"Finished detection in {(DateTime.Now - detectStart).TotalMilliseconds} ms. {numLeaked} of those are leaked managed shells");
132+
File.WriteAllText("leaked_objects.txt", ret.ToString());
112133
}
113134
}

0 commit comments

Comments
 (0)