private void DrawSpecificTexture2D(NativeUnityEngineObject nativeObject) { if (nativeObject.className != "Texture2D") { _textureObject = null; return; } EditorGUILayout.HelpBox("Watching Texture Detail Data is only for Editor.", MessageType.Warning, true); if (_prevInstance != nativeObject.instanceID) { _textureObject = EditorUtility.InstanceIDToObject(nativeObject.instanceID) as Texture2D; _prevInstance = nativeObject.instanceID; } if (_textureObject != null) { EditorGUILayout.LabelField("textureInfo: " + _textureObject.width + "x" + _textureObject.height + " " + _textureObject.format); EditorGUILayout.ObjectField(_textureObject, typeof(Texture2D)); _textureSize = EditorGUILayout.Slider(_textureSize, 100.0f, 1024.0f); GUILayout.Label(_textureObject, GUILayout.Width(_textureSize), GUILayout.Height(_textureSize * _textureObject.height / _textureObject.width)); } else { EditorGUILayout.LabelField("Can't instance texture,maybe it was alreadt released."); } }
private void DrawSpecificTexture2D(NativeUnityEngineObject nativeObject) { if (nativeObject.className != "Texture2D") { _textureObject = null; return; } EditorGUILayout.HelpBox("Previewing Texture2D only works correctly when profiling inside the editor.", MessageType.Warning, true); if (_prevInstance != nativeObject.instanceID) { // Attempt to match the texture to one in editor _textureObject = GetTexture(nativeObject); _prevInstance = nativeObject.instanceID; } if (_textureObject != null) { EditorGUILayout.LabelField("textureInfo: " + _textureObject.width + "x" + _textureObject.height + " " + _textureObject.format); EditorGUILayout.ObjectField(_textureObject, typeof(Texture2D), false); _textureSize = EditorGUILayout.Slider(_textureSize, 100.0f, 1024.0f); GUILayout.Label(_textureObject, GUILayout.Width(_textureSize), GUILayout.Height(_textureSize * _textureObject.height / _textureObject.width)); } else { EditorGUILayout.LabelField("Can't instance the texture, maybe it was already released."); } }
public static CrawledMemorySnapshot Unpack(PackedCrawlerData packedCrawlerData) { var packedSnapshot = packedCrawlerData.packedMemorySnapshot; var result = new CrawledMemorySnapshot { //nativeObjects = packedSnapshot.nativeObjects.Select(packedNativeUnityEngineObject => UnpackNativeUnityEngineObject(packedSnapshot, packedNativeUnityEngineObject)).ToArray(), managedObjects = packedCrawlerData.managedObjects.Select(pm => UnpackManagedObject(packedSnapshot, pm)).ToArray(), gcHandles = packedSnapshot.gcHandles.Select(pgc => UnpackGCHandle(packedSnapshot)).ToArray(), staticFields = packedSnapshot.typeDescriptions.Where(t => t.staticFieldBytes != null & t.staticFieldBytes.Length > 0).Select(t => UnpackStaticFields(t)).ToArray(), typeDescriptions = packedSnapshot.typeDescriptions, managedHeap = packedSnapshot.managedHeapSections, nativeTypes = packedSnapshot.nativeTypes, virtualMachineInformation = packedSnapshot.virtualMachineInformation }; PackedNativeUnityEngineObject[] objects = packedSnapshot.nativeObjects; List <NativeUnityEngineObject> temp_list = new List <NativeUnityEngineObject>(); for (int i = 0; i < objects.Length; i++) { NativeUnityEngineObject nativeObj = UnpackNativeUnityEngineObjectIgnoreUnityBuiltin(packedSnapshot, objects[i]); if (nativeObj == null) { continue; } temp_list.Add(nativeObj); } result.nativeObjects = temp_list.ToArray(); var combined = new ThingInMemory[0].Concat(result.gcHandles).Concat(result.nativeObjects).Concat(result.staticFields).Concat(result.managedObjects).ToArray(); result.allObjects = combined; var referencesLists = MakeTempLists(combined); var referencedByLists = MakeTempLists(combined); foreach (var connection in packedCrawlerData.connections) { if (connection.@from >= referencesLists.Length || connection.to >= combined.Length) { continue; } referencesLists[connection.@from].Add(combined[connection.to]); referencedByLists[connection.to].Add(combined[connection.@from]); } for (var i = 0; i != combined.Length; i++) { combined[i].references = referencesLists[i].ToArray(); combined[i].referencedBy = referencedByLists[i].ToArray(); } return(result); }
private bool CompareNativeUnityEngineObject(NativeUnityEngineObject obj1, NativeUnityEngineObject obj2) { return(((obj1.instanceID == obj2.instanceID && this._needCompareInstanceID) || !this._needCompareInstanceID) && obj1.size == obj2.size && obj1.classID == obj2.classID && obj1.className == obj2.className && obj1.name == obj2.name && obj1.isPersistent == obj2.isPersistent && obj1.isDontDestroyOnLoad == obj2.isDontDestroyOnLoad && obj1.isManager == obj2.isManager && obj1.hideFlags == obj2.hideFlags); }
private void DrawNativeObject(NativeUnityEngineObject nativeObject) { using (var scope = new EditorGUILayout.HorizontalScope()) { string result = string.Format("classname:{0}, name: {1}, size: {2}", nativeObject.className, nativeObject.name, ToMemorySize(nativeObject.size)); EditorGUILayout.LabelField(result, GUILayout.MaxWidth(500)); EditorGUILayout.Space(); if (GUILayout.Button("Select", GUILayout.Width(50))) { this._diffWindow.SelectThing(nativeObject); this._diffWindow.Repaint(); } } }
private Texture2D GetTexture(NativeUnityEngineObject nativeObject) { // If the texture has a name, try to match it to a loaded object if (!string.IsNullOrEmpty(nativeObject.name)) { Texture2D[] loadedTextures = Resources.FindObjectsOfTypeAll <Texture2D>(); for (int i = 0; i < loadedTextures.Length; i++) { if (loadedTextures[i].name == nativeObject.name) { return(loadedTextures[i]); } } } // None matched return(null); }
internal bool IsRoot(ThingInMemory thing, out string reason) { reason = null; if (thing is StaticFields) { reason = "Static fields are global variables. Anything they reference will not be unloaded."; return(true); } if (thing is ManagedObject) { return(false); } if (thing is GCHandle) { return(false); } NativeUnityEngineObject nativeObject = thing as NativeUnityEngineObject; if (nativeObject == null) { throw new ArgumentException("Unknown type: " + thing.GetType()); } if (nativeObject.isManager) { reason = "this is an internal unity'manager' style object, which is a global object that will never be unloaded"; return(true); } if (nativeObject.isDontDestroyOnLoad) { reason = "DontDestroyOnLoad() was called on this object, so it will never be unloaded"; return(true); } if ((nativeObject.hideFlags & HideFlags.DontUnloadUnusedAsset) != 0) { reason = "the DontUnloadUnusedAsset hideflag is set on this object. Unity's builtin resources set this flag. Users can also set the flag themselves"; return(true); } if (nativeObject.isPersistent) { return(false); } if (IsComponent(nativeObject.classID)) { reason = "this is a component, living on a gameobject, that is either part of the loaded scene, or was generated by script. It will be unloaded on next scene load."; return(true); } if (IsGameObject(nativeObject.classID)) { reason = "this is a gameobject, that is either part of the loaded scene, or was generated by script. It will be unloaded on next scene load if nobody is referencing it"; return(true); } if (IsAssetBundle(nativeObject.classID)) { reason = "this object is an assetbundle, which is never unloaded automatically, but only through an explicit .Unload() call."; return(true); } reason = "This object is a root, but the memory profiler UI does not yet understand why"; return(true); }
private string getRemoveDiffTypeStr(NativeUnityEngineObject things) { return(things.className.Replace(sDiffType.AdditiveType, "").Replace(sDiffType.ModificationType, ""). Replace(sDiffType.NegativeType, "")); }
internal void Draw() { GUILayout.BeginArea(new Rect(_hostWindow.position.width - width, _hostWindow.topMargin, width, _hostWindow.position.height - _hostWindow.topMargin)); _scrollPosition = GUILayout.BeginScrollView(_scrollPosition); GUILayout.BeginHorizontal(); GUI.enabled = _backSelected.Count > 1; if (GUILayout.Button(string.Format("Back ({0})", Math.Max(0, _backSelected.Count - 1)))) { _backSelected.Pop(); if (_nextSelected.Count == 0 || _backSelected.Peek() != _nextSelected.Peek()) { _nextSelected.Push(_backSelected.Peek()); } _hostWindow.SelectThing(_backSelected.Peek()); } GUI.enabled = true; GUI.enabled = _nextSelected.Count > 1; if (GUILayout.Button(string.Format("Next ({0})", Math.Max(0, _nextSelected.Count - 1)))) { _nextSelected.Pop(); _hostWindow.SelectThing(_nextSelected.Peek()); } GUI.enabled = true; GUILayout.EndHorizontal(); if (_unpackedCrawl != null) { GUILayout.Label(string.Format("Total memory: {0}", EditorUtility.FormatBytes(_unpackedCrawl.totalSize))); } if (_selectedThing == null) { GUILayout.Label("Select an object to see more info"); } else { NativeUnityEngineObject nativeObject = _selectedThing as NativeUnityEngineObject; if (nativeObject != null) { GUILayout.Label("NativeUnityEngineObject", EditorStyles.boldLabel); GUILayout.Space(5); EditorGUILayout.LabelField("Name", nativeObject.name); EditorGUILayout.LabelField("ClassName", nativeObject.className); EditorGUILayout.LabelField("Memory amount", EditorUtility.FormatBytes(_selectedThing.size)); EditorGUILayout.LabelField("instanceID", nativeObject.instanceID.ToString()); EditorGUILayout.LabelField("isDontDestroyOnLoad", nativeObject.isDontDestroyOnLoad.ToString()); EditorGUILayout.LabelField("isPersistent", nativeObject.isPersistent.ToString()); EditorGUILayout.LabelField("isManager", nativeObject.isManager.ToString()); EditorGUILayout.LabelField("hideFlags", nativeObject.hideFlags.ToString()); DrawSpecificTexture2D(nativeObject); } ManagedObject managedObject = _selectedThing as ManagedObject; if (managedObject != null) { GUILayout.Label("ManagedObject"); EditorGUILayout.LabelField("Type", managedObject.typeDescription.name); EditorGUILayout.LabelField("Address", managedObject.address.ToString("X")); EditorGUILayout.LabelField("size", managedObject.size.ToString()); if (managedObject.typeDescription.name == "System.String") { EditorGUILayout.LabelField("value", StringTools.ReadString(_unpackedCrawl.managedHeap.Find(managedObject.address, _unpackedCrawl.virtualMachineInformation), _unpackedCrawl.virtualMachineInformation)); } DrawFields(managedObject); if (managedObject.typeDescription.isArray) { DrawArray(managedObject); } } if (_selectedThing is GCHandle) { GUILayout.Label("GCHandle"); EditorGUILayout.LabelField("size", _selectedThing.size.ToString()); } StaticFields staticFields = _selectedThing as StaticFields; if (staticFields != null) { GUILayout.Label("Static Fields"); GUILayout.Label("Of type: " + staticFields.typeDescription.name); GUILayout.Label("size: " + staticFields.size); DrawFields(staticFields.typeDescription, new BytesAndOffset() { bytes = staticFields.typeDescription.staticFieldBytes, offset = 0, pointerSize = _unpackedCrawl.virtualMachineInformation.pointerSize }, true); } if (managedObject == null) { GUILayout.Space(10); GUILayout.BeginHorizontal(); GUILayout.Label("References:", labelWidth); GUILayout.BeginVertical(); DrawLinks(_selectedThing.references); GUILayout.EndVertical(); GUILayout.EndHorizontal(); } GUILayout.Space(10); GUILayout.Label("Referenced by:"); DrawLinks(_selectedThing.referencedBy); GUILayout.Space(10); if (_shortestPath != null) { if (_shortestPath.Length > 1) { GUILayout.Label("ShortestPathToRoot"); DrawLinks(_shortestPath); } string reason; _shortestPathToRootFinder.IsRoot(_shortestPath.Last(), out reason); GUILayout.Label("This is a root because:"); GUILayout.TextArea(reason); } else { GUILayout.TextArea("No root is keeping this object alive. It will be collected next UnloadUnusedAssets() or scene load"); } } GUILayout.EndScrollView(); GUILayout.EndArea(); }
private int CompareData(int id1, int id2, int col) { ThingInMemory thing1 = m_unpackedCrawl.allObjects[id1]; NativeUnityEngineObject nativeObject1 = thing1 as NativeUnityEngineObject; ThingInMemory thing2 = m_unpackedCrawl.allObjects[id2]; NativeUnityEngineObject nativeObject2 = thing2 as NativeUnityEngineObject; switch ((Column)col) { case Column.Name: if (nativeObject1 != null && nativeObject2 != null) { return(nativeObject1.name.CompareTo(nativeObject2.name)); } else if (nativeObject1 != null) { return(-1); } else if (nativeObject2 != null) { return(1); } else { return(0); } case Column.Type: // this depends on the fact that HighLevelAPI.allGameObjects concatenates objects in the order we want return(id1 - id2); case Column.Size: return(-thing1.size.CompareTo(thing2.size)); case Column.ClassName: if (nativeObject1 != null && nativeObject2 != null) { return(nativeObject1.className.CompareTo(nativeObject2.className)); } else if (nativeObject1 != null) { return(-1); } else if (nativeObject2 != null) { return(1); } else { return(0); } case Column.InstanceID: if (nativeObject1 != null && nativeObject2 != null) { return(nativeObject1.instanceID.CompareTo(nativeObject2.instanceID)); } else if (nativeObject1 != null) { return(-1); } else if (nativeObject2 != null) { return(1); } else { return(0); } } return(0); }
private GUIContent DataForGrid(int id, int col) { string str = "undefined"; ThingInMemory thing = m_unpackedCrawl.allObjects[id]; NativeUnityEngineObject nativeObject = thing as NativeUnityEngineObject; switch ((Column)col) { case Column.Name: if (nativeObject != null) { str = nativeObject.name; } if (str.Equals("")) { str = "unnamed"; } if (thing.ignored) { str = "<filtered>"; } break; case Column.Type: str = ThingTypeToString(indexToThingType(id)); if (thing.ignored) { str = "<filtered>"; } break; case Column.Size: str = EditorUtility.FormatBytes(thing.size); if (thing.ignored) { str = "<filtered>"; } break; case Column.ClassName: if (nativeObject != null) { str = nativeObject.className; } if (thing.ignored) { str = "<filtered>"; } break; case Column.InstanceID: if (nativeObject != null) { str = nativeObject.instanceID.ToString(); } if (thing.ignored) { str = "<filtered>"; } break; } return(new GUIContent(str)); }