public static List <RootPathInformation> AnalyzeRootPath(MessageBus msgBus, ClrDumpObject clrDumpObject) { ClrDump clrDump = clrDumpObject.ClrDump; ulong address = clrDumpObject.Address; CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analysing Root Path...", token); if (token.IsCancellationRequested) { msgBus.EndTask("Root Path analysis: cancelled."); return(null); } msgBus.Status("Analysing Root Path: collecting root instances..."); var roots = new HashSet <ulong>(clrDump.EnumerateClrRoots.Select(clrRoot => clrRoot.Object)); if (logger.IsDebugEnabled) { logger.Debug("Roots: " + Str(roots)); } List <ulong> bestPath = null; var currentPath = new List <ulong>(); bool result = FindShortestPath(address, currentPath, ref bestPath, clrDump.GetReferers, roots.Contains, new Dictionary <ulong, List <ulong> >()); if (!result) { currentPath = new List <ulong>(); FindShortestPath(address, currentPath, ref bestPath, clrDump.GetReferers, (addr) => !clrDump.HasReferers(addr), new Dictionary <ulong, List <ulong> >()); } List <RootPathInformation> path = new List <RootPathInformation>(); ulong prevAddress = address; if (bestPath != null) { foreach (var refAddress in bestPath) { var refClrDumpObject = new ClrDumpObject(clrDump, clrDump.GetObjectType(refAddress), refAddress); var fieldName = refAddress == address ? " - " : clrDump.GetFieldNameReference(prevAddress, refAddress); fieldName = TypeHelpers.RealName(fieldName); path.Add(new RootPathInformation(refClrDumpObject, fieldName)); prevAddress = refAddress; } msgBus.EndTask("Root Path found."); } else { msgBus.EndTask("Root Path NOT found."); } return(path); }
public List <ClrRoot> GetClrRoots() { List <ClrRoot> clrRoots = new List <ClrRoot>(); CancellationTokenSource source = new CancellationTokenSource(); var token = source.Token; MessageBus.BeginTask("Looking for ClrRoots...", source); int n = 0; foreach (var obj in Runtime.Heap.EnumerateRoots()) { if (token.IsCancellationRequested) { break; } n++; if (n % 512 == 0) { MessageBus.Status($"Looking for ClrRoots: {clrRoots.Count:###,###,###,##0}"); } clrRoots.Add(obj); } if (token.IsCancellationRequested) { MessageBus.EndTask($"ClrRoots (cancelled): {clrRoots.Count:###,###,###,##0} found."); } else { MessageBus.EndTask($"ClrRoots : {clrRoots.Count:###,###,###,##0} found."); } return(clrRoots); }
public List <BlockingObject> GetBlockingObjects() { List <BlockingObject> blockingObjects = new List <BlockingObject>(); CancellationTokenSource source = new CancellationTokenSource(); var token = source.Token; MessageBus.BeginTask("Looking for blocking objects...", source); int n = 0; foreach (var obj in Runtime.GetHeap().EnumerateBlockingObjects()) { if (token.IsCancellationRequested) { break; } n++; if (n % 512 == 0) { MessageBus.Status($"Looking for blocking objects: {blockingObjects.Count:###,###,###,##0}"); } blockingObjects.Add(obj); } if (token.IsCancellationRequested) { MessageBus.EndTask($"Blocking objects (cancelled): {blockingObjects.Count:###,###,###,##0} found."); } else { MessageBus.EndTask($"Blocking objects: {blockingObjects.Count:###,###,###,##0} found."); } return(blockingObjects); }
public static List<RootPathInformation> AnalyzeRootPath(MessageBus msgBus, ClrDumpObject clrDumpObject) { ClrDump clrDump = clrDumpObject.ClrDump; ulong address = clrDumpObject.Address; CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analysing Root Path...", token); if( token.IsCancellationRequested) { msgBus.EndTask("Root Path analysis: cancelled."); return null; } msgBus.Status("Analysing Root Path: collecting root instances..."); var roots = new HashSet<ulong>(clrDump.EnumerateClrRoots.Select(clrRoot => clrRoot.Object)); if (logger.IsDebugEnabled) { logger.Debug("Roots: " + Str(roots)); } List<ulong> bestPath = null; var currentPath = new List<ulong>(); currentPath.Add(address); bool result = FindShortestPath(currentPath, ref bestPath, clrDump); List<RootPathInformation> path = new List<RootPathInformation>(); ulong prevAddress = address; if (bestPath != null) { foreach (var refAddress in bestPath) { var refClrDumpObject = new ClrDumpObject(clrDump, clrDump.GetObjectType(refAddress), refAddress); var fieldName = refAddress == address ? " - " : clrDump.GetFieldNameReference(prevAddress, refAddress); fieldName = TypeHelpers.RealName(fieldName); path.Add(new RootPathInformation(refClrDumpObject, fieldName)); prevAddress = refAddress; } msgBus.EndTask("Root Path found."); } else { msgBus.EndTask("Root Path NOT found."); } return path; }
internal static List <ArraysInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { CancellationTokenSource token = new CancellationTokenSource(); var arrays = new List <ArraysInformation>(); msgBus.BeginTask("Analyzing arrays...", token); int n = 0; clrDump.Run(() => { var arrayTypes = clrDump.AllTypes.Where(t => t.IsArray); int nbArrayType = arrayTypes.Count(); foreach (var type in arrayTypes) { string typeName = type.Name; msgBus.Status($"Analyzing array type: {typeName} ({n:###,###,###,##0}/{nbArrayType:###,###,###,##0})"); if (token.IsCancellationRequested) { return; } n++; ulong nbInstances = 0; ulong totalSize = 0; ulong totalLength = 0; ulong maxLength = 0; foreach (var address in clrDump.EnumerateInstances(type)) { nbInstances++; var length = (ulong)(type.GetArrayLength(address)); maxLength = Math.Max(maxLength, length); totalSize += type.GetSize(address); totalLength += length; if (nbInstances % 512 == 0) { msgBus.Status($"Analyzing array: #{nbInstances:###,###,###,##0} for type: {typeName}"); if (token.IsCancellationRequested) { return; } } } arrays.Add(new ArraysInformation(new ClrDumpType(clrDump, type), nbInstances, totalLength, maxLength, totalSize)); } }); msgBus.EndTask($"Arrays analyzed. Types: {n:###,###,###,##0}"); return(arrays); }
internal static List <StringInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { var stringType = clrDump.GetClrType(typeof(string).FullName); var stringInstances = clrDump.EnumerateInstances(stringType); int nbStrings = clrDump.CountInstances(stringType); Dictionary <string, List <ulong> > result = new Dictionary <string, List <ulong> >(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing strings...", token); int n = 0; clrDump.Run(() => { foreach (var address in stringInstances) { if (token.IsCancellationRequested) { return; } n++; var value = SimpleValueHelper.GetSimpleValue(address, stringType, false) as string; if (value == null) { continue; } List <ulong> addresses; if (!result.TryGetValue(value, out addresses)) { addresses = new List <ulong>(); result[value] = addresses; } addresses.Add(address); if (n % 1024 == 0) { float pct = (float)n / nbStrings; msgBus.Status($"Analyzing strings: {pct:p2}, n= {n:###,###,###,##0} / {nbStrings:###,###,###,##0}"); } } }); msgBus.EndTask($"Strings analyzed. Instances: {n:###,###,###,##0}, unique values: {result.Count:###,###,###,##0}"); var strings = result.Select(kvp => new StringInformation(kvp.Key, kvp.Value)).ToList(); return(strings); }
internal static List<ArraysInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { CancellationTokenSource token = new CancellationTokenSource(); var arrays = new List<ArraysInformation>(); msgBus.BeginTask("Analyzing arrays...", token); int n = 0; clrDump.Run(() => { var arrayTypes = clrDump.AllTypes.Where(t => t.IsArray); int nbArrayType = arrayTypes.Count(); foreach (var type in arrayTypes) { string typeName = type.Name; msgBus.Status($"Analyzing array type: {typeName} ({n:###,###,###,##0}/{nbArrayType:###,###,###,##0})"); if ( token.IsCancellationRequested ) { return; } n++; ulong nbInstances = 0; ulong totalSize = 0; ulong totalLength = 0; ulong maxLength = 0; foreach (var address in clrDump.EnumerateInstances(type)) { nbInstances++; var length = (ulong)(type.GetArrayLength(address)); maxLength = Math.Max(maxLength, length); totalSize += type.GetSize(address); totalLength += length; if (nbInstances % 512 == 0) { msgBus.Status($"Analyzing array: #{nbInstances:###,###,###,##0} for type: {typeName}"); if (token.IsCancellationRequested) { return; } } } arrays.Add(new ArraysInformation(new ClrDumpType(clrDump, type), nbInstances, totalLength, maxLength, totalSize)); } }); msgBus.EndTask($"Arrays analyzed. Types: {n:###,###,###,##0}"); return arrays; }
internal static List<StringInformation> Analyse(ClrDump clrDump, MessageBus msgBus) { var stringType = clrDump.GetClrType(typeof(string).FullName); var stringInstances = clrDump.EnumerateInstances(stringType); int nbStrings = clrDump.CountInstances(stringType); Dictionary <string, List<ulong>> result = new Dictionary<string, List<ulong>>(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing strings...", token); int n = 0; clrDump.Run(() => { foreach (var address in stringInstances) { if( token.IsCancellationRequested) { return; } n++; var value = SimpleValueHelper.GetSimpleValue(address, stringType, false) as string; if (value == null) { continue; } List<ulong> addresses; if( ! result.TryGetValue(value, out addresses)) { addresses = new List<ulong>(); result[value] = addresses; } addresses.Add(address); if( n % 1024 == 0) { float pct = (float)n / nbStrings; msgBus.Status($"Analyzing strings: {pct:p2}, n= {n:###,###,###,##0} / {nbStrings:###,###,###,##0}"); } } }); msgBus.EndTask($"Strings analyzed. Instances: {n:###,###,###,##0}, unique values: {result.Count:###,###,###,##0}"); var strings = result.Select(kvp => new StringInformation(kvp.Key, kvp.Value)).ToList(); return strings; }
public static List<ArrayInstanceInformation> Analyze(ArraysAddressList arrayAddressList, MessageBus msgBus) { var clrDump = arrayAddressList.ClrDump; var clrType = arrayAddressList.ClrType; var typeName = clrType.Name; CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask($"Analyzing arrays: {typeName}...", token); List<ArrayInstanceInformation> result = clrDump.Eval(() => { var tmp = new List<ArrayInstanceInformation>(); var count = arrayAddressList.Addresses.Count; HashSet<object> addresses = new HashSet<object>(); for (int i=0; i < count; i++) { if (token.IsCancellationRequested) { break; } var address = arrayAddressList.Addresses[i]; int length = clrType.GetArrayLength(address); if (i % 128 == 0) { msgBus.Status($"Analyzing instance: {i:###,###,###,##0} / {count:###,###,###,##0}"); } float? nullRatio = null; float? uniqueRatio = null; if ( clrType.ContainsPointers ) { int nbNull = 0; addresses.Clear(); for (int j=0; j < length; j++) { object elemAddress = clrType.GetArrayElementValue(address, j); if( elemAddress is ulong && (ulong)elemAddress == 0) { nbNull++; } else if (elemAddress == null) { nbNull++; } else { addresses.Add(elemAddress); } if (j % 1024 == 0 && j !=0) { msgBus.Status($"Analyzing instance: {i:###,###,###,##0} / {count:###,###,###,##0}, element {j:###,###,###,##0} / {length:###,###,###,##0}"); } } nullRatio = ((float)nbNull) / length; uniqueRatio = ((float)addresses.Count+nbNull) / length; } ArrayInstanceInformation info = new ArrayInstanceInformation(clrDump, clrType, address, length, nullRatio, uniqueRatio); tmp.Add(info); } return tmp; }); msgBus.EndTask("Arrays analyzed."); return result; }
public static List <ReferersInformation> AnalyzeReferers(MessageBus msgBus, ClrDump clrDump, HashSet <ulong> addresses) { var referers = new List <ReferersInformation>(); var dicoByRefererType = new Dictionary <ClrType, Dictionary <string, ReferersInformation> >(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing referers...", token); Application.DoEvents(); // todo: avoid this call to Application.DoEvents() int count = addresses.Count; int i = 0; foreach (var address in addresses) { i++; if (token.IsCancellationRequested) { msgBus.EndTask("Referers analyze: cancelled."); return(referers); } if (i % 1024 == 0) { msgBus.Status($"Analyzing referers: {(double)i/count:p2}, {i:###,###,###,##0} / {count:###,###,###,##0}..."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() } foreach (var refererAddress in clrDump.EnumerateReferers(address)) { var type = clrDump.GetObjectType(refererAddress); string field; if (type.IsArray) { field = "[ x ]"; } else { field = clrDump.GetFieldNameReference(address, refererAddress); field = TypeHelpers.RealName(field); } Dictionary <string, ReferersInformation> dicoRefInfoByFieldName; if (!dicoByRefererType.TryGetValue(type, out dicoRefInfoByFieldName)) { dicoRefInfoByFieldName = new Dictionary <string, ReferersInformation>(); dicoByRefererType[type] = dicoRefInfoByFieldName; } ReferersInformation referersInformation; if (!dicoRefInfoByFieldName.TryGetValue(field, out referersInformation)) { referersInformation = new ReferersInformation(clrDump, type, field, msgBus, count); dicoRefInfoByFieldName[field] = referersInformation; } referersInformation.References.Add(address); referersInformation.Instances.Add(refererAddress); } } foreach (var kvpType in dicoByRefererType) { var type = kvpType.Key; foreach (var kvpField in kvpType.Value) { var refInfo = kvpField.Value; referers.Add(refInfo); refInfo.Init(); } } msgBus.EndTask("Referers analyzed."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() return(referers); }
public static List <ArrayInstanceInformation> Analyze(ArraysAddressList arrayAddressList, MessageBus msgBus) { var clrDump = arrayAddressList.ClrDump; var clrType = arrayAddressList.ClrType; var typeName = clrType.Name; CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask($"Analyzing arrays: {typeName}...", token); List <ArrayInstanceInformation> result = clrDump.Eval(() => { var tmp = new List <ArrayInstanceInformation>(); var count = arrayAddressList.Addresses.Count; HashSet <object> addresses = new HashSet <object>(); for (int i = 0; i < count; i++) { if (token.IsCancellationRequested) { break; } var address = arrayAddressList.Addresses[i]; int length = clrType.GetArrayLength(address); if (i % 128 == 0) { msgBus.Status($"Analyzing instance: {i:###,###,###,##0} / {count:###,###,###,##0}"); } float?nullRatio = null; float?uniqueRatio = null; if (clrType.ContainsPointers) { int nbNull = 0; addresses.Clear(); for (int j = 0; j < length; j++) { object elemAddress = clrType.GetArrayElementValue(address, j); if (elemAddress is ulong && (ulong)elemAddress == 0) { nbNull++; } else if (elemAddress == null) { nbNull++; } else { addresses.Add(elemAddress); } if (j % 1024 == 0 && j != 0) { msgBus.Status($"Analyzing instance: {i:###,###,###,##0} / {count:###,###,###,##0}, element {j:###,###,###,##0} / {length:###,###,###,##0}"); } } nullRatio = ((float)nbNull) / length; uniqueRatio = ((float)addresses.Count + nbNull) / length; } ArrayInstanceInformation info = new ArrayInstanceInformation(clrDump, clrType, address, length, nullRatio, uniqueRatio); tmp.Add(info); } return(tmp); }); msgBus.EndTask("Arrays analyzed."); return(result); }
public static List<ReferersInformation> AnalyzeReferers(MessageBus msgBus, ClrDump clrDump, HashSet<ulong> addresses) { var referers = new List<ReferersInformation>(); var dicoByRefererType = new Dictionary<ClrType, Dictionary<string, ReferersInformation>>(); CancellationTokenSource token = new CancellationTokenSource(); msgBus.BeginTask("Analyzing referers...", token); Application.DoEvents(); // todo: avoid this call to Application.DoEvents() int count = addresses.Count; int i = 0; foreach(var address in addresses) { i++; if( token.IsCancellationRequested) { msgBus.EndTask("Referers analyze: cancelled."); return referers; } if ( i % 1024 == 0) { msgBus.Status($"Analyzing referers: {(double)i/count:p2}, {i:###,###,###,##0} / {count:###,###,###,##0}..."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() } foreach( var refererAddress in clrDump.EnumerateReferers(address)) { var type = clrDump.GetObjectType(refererAddress); string field; if (type.IsArray) { field = "[ x ]"; } else { field = clrDump.GetFieldNameReference(address, refererAddress); field = TypeHelpers.RealName(field); } Dictionary<string, ReferersInformation> dicoRefInfoByFieldName; if( ! dicoByRefererType.TryGetValue(type, out dicoRefInfoByFieldName)) { dicoRefInfoByFieldName = new Dictionary<string, ReferersInformation>(); dicoByRefererType[type] = dicoRefInfoByFieldName; } ReferersInformation referersInformation; if ( ! dicoRefInfoByFieldName.TryGetValue(field, out referersInformation)) { referersInformation = new ReferersInformation(clrDump, type, field, msgBus, count); dicoRefInfoByFieldName[field] = referersInformation; } referersInformation.References.Add(address); referersInformation.Instances.Add(refererAddress); } } foreach(var kvpType in dicoByRefererType) { var type = kvpType.Key; foreach(var kvpField in kvpType.Value) { var refInfo = kvpField.Value; referers.Add(refInfo); refInfo.Init(); } } msgBus.EndTask("Referers analyzed."); Application.DoEvents();// todo: avoid this call to Application.DoEvents() return referers; }