Beispiel #1
0
        void OnHeapReceivedSaveOnly(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot)
        {
            UnityEditor.MemoryProfiler.MemorySnapshot.OnSnapshotReceived -= OnHeapReceivedSaveOnly;

            EditorUtility.DisplayProgressBar(HeGlobals.k_Title, "Saving memory...", 0.5f);
            try
            {
                var args = new MemorySnapshotProcessingArgs();
                args.source = snapshot;
                args.excludeNativeFromConnections = excludeNativeFromConnections;

                var heap = PackedMemorySnapshot.FromMemoryProfiler(args);
                heap.SaveToFile(autoSavePath);
                HeMruFiles.AddPath(autoSavePath);
                ShowNotification(new GUIContent(string.Format("Memory snapshot saved as\n'{0}'", autoSavePath)));
            }
            catch
            {
                m_CloseDueToError = true;
                throw;
            }
            finally
            {
                m_IsCapturing = false;
                m_Repaint     = true;
                EditorUtility.ClearProgressBar();
            }
        }
Beispiel #2
0
        void OnHeapReceived(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot)
        {
            UnityEditor.MemoryProfiler.MemorySnapshot.OnSnapshotReceived -= OnHeapReceived;

            EditorUtility.DisplayProgressBar(HeGlobals.k_Title, "Reading memory...", 0.5f);
            try
            {
                m_Heap = null;

                if (useThreads)
                {
                    var job = new ReceiveThreadJob
                    {
                        threadFunc = ReceiveHeapThreaded,
                        snapshot   = snapshot
                    };
                    ScheduleJob(job);
                }
                else
                {
                    EditorUtility.DisplayProgressBar(HeGlobals.k_Title, "Analyzing memory...", 0.75f);
                    ReceiveHeapThreaded(snapshot);
                }
            }
            finally
            {
                snapshotPath  = string.Format("Captured Snapshot at {0}", DateTime.Now.ToShortTimeString());
                m_IsCapturing = false;
                m_Repaint     = true;
                EditorUtility.ClearProgressBar();
            }
        }
Beispiel #3
0
        void OnSnapshotReceived(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot)
        {
            UnityEditor.MemoryProfiler.MemorySnapshot.OnSnapshotReceived -= OnSnapshotReceived;

            var args = new MemorySnapshotProcessingArgs();

            args.source = snapshot;
            args.excludeNativeFromConnections = false;

            m_snapshot = PackedMemorySnapshot.FromMemoryProfiler(args);
        }
Beispiel #4
0
        static void VerifyMemoryProfilerSnapshot(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot)
        {
            if (snapshot == null)
            {
                throw new Exception("No snapshot was found.");
            }

            if (snapshot.typeDescriptions == null || snapshot.typeDescriptions.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'typeDescriptions'. This is a known issue when using .NET 4.x Scripting Runtime.\n(Case 1079363) PackedMemorySnapshot: .NET 4.x Scripting Runtime breaks memory snapshot");
            }

            if (snapshot.managedHeapSections == null || snapshot.managedHeapSections.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'managedHeapSections'. This is a known issue when using .NET 4.x Scripting Runtime.\n(Case 1079363) PackedMemorySnapshot: .NET 4.x Scripting Runtime breaks memory snapshot");
            }

            if (snapshot.gcHandles == null || snapshot.gcHandles.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'gcHandles'. This is a known issue when using .NET 4.x Scripting Runtime.\n(Case 1079363) PackedMemorySnapshot: .NET 4.x Scripting Runtime breaks memory snapshot");
            }

            if (snapshot.nativeTypes == null || snapshot.nativeTypes.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'nativeTypes'.");
            }

            if (snapshot.nativeObjects == null || snapshot.nativeObjects.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'nativeObjects'.");
            }

            if (snapshot.connections == null || snapshot.connections.Length == 0)
            {
                throw new Exception("The snapshot does not contain any 'connections'.");
            }
        }
Beispiel #5
0
        public static bool Convert(UnityEditor.MemoryProfiler.PackedMemorySnapshot snapshot, string writePath)
        {
            MemorySnapshotFileWriter writer = null;

            try
            {
                writer = new MemorySnapshotFileWriter(writePath);
            }
            catch (Exception e)
            {
                Debug.LogError("Failed to create snapshot file: " + e.Message);
                return(false);
            }

            //snapshot version will always be the remap connections version as that is the last change affecting this format
            writer.WriteEntry(EntryType.Metadata_Version, (uint)FormatHistory.NativeConnectionsAsInstanceIdsVersion);

            //timestamp with conversion date
            writer.WriteEntry(EntryType.Metadata_RecordDate, (ulong)DateTime.Now.Ticks);

            //prepare metadata
            string platform         = "Unknown";
            string content          = "Converted Snapshot";
            int    stringDataLength = (platform.Length + content.Length) * sizeof(char);

            byte[] metaDataBytes = new byte[stringDataLength + (sizeof(int) * 3)]; // add space for serializing the lengths of the strings

            int offset = 0;

            offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, content.Length);
            offset = ExperimentalMemoryProfiler.WriteStringToByteArray(metaDataBytes, offset, content);

            offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, platform.Length);
            offset = ExperimentalMemoryProfiler.WriteStringToByteArray(metaDataBytes, offset, platform);

            offset = ExperimentalMemoryProfiler.WriteIntToByteArray(metaDataBytes, offset, 0);

            // Write metadata
            writer.WriteEntryArray(EntryType.Metadata_UserMetadata, metaDataBytes);

            writer.WriteEntry(EntryType.Metadata_CaptureFlags, (UInt32)CaptureFlags.ManagedObjects); //capture just managed

            // Write managed heap sections
            for (int i = 0; i < snapshot.managedHeapSections.Length; ++i)
            {
                var heapSection = snapshot.managedHeapSections[i];
                writer.WriteEntry(EntryType.ManagedHeapSections_StartAddress, heapSection.m_StartAddress);
                writer.WriteEntryArray(EntryType.ManagedHeapSections_Bytes, heapSection.m_Bytes);
            }

            // Write managed types
            int fieldDescriptionCount = 0;

            for (int i = 0; i < snapshot.typeDescriptions.Length; ++i)
            {
                var type = snapshot.typeDescriptions[i];
                writer.WriteEntry(EntryType.TypeDescriptions_Flags, (UInt32)type.m_Flags);
                writer.WriteEntry(EntryType.TypeDescriptions_BaseOrElementTypeIndex, type.baseOrElementTypeIndex);
                writer.WriteEntry(EntryType.TypeDescriptions_TypeIndex, type.typeIndex);

                if (!type.isArray)
                {
                    var   typeFields   = type.fields;
                    int[] fieldIndices = new int[typeFields.Length];

                    for (int j = 0; j < typeFields.Length; ++j)
                    {
                        var field = typeFields[j];
                        fieldIndices[j] = fieldDescriptionCount;
                        ++fieldDescriptionCount;

                        writer.WriteEntry(EntryType.FieldDescriptions_Offset, field.offset);
                        writer.WriteEntry(EntryType.FieldDescriptions_TypeIndex, field.typeIndex);
                        writer.WriteEntry(EntryType.FieldDescriptions_Name, field.name);
                        writer.WriteEntry(EntryType.FieldDescriptions_IsStatic, field.isStatic);
                    }

                    writer.WriteEntryArray(EntryType.TypeDescriptions_FieldIndices, fieldIndices);
                    writer.WriteEntryArray(EntryType.TypeDescriptions_StaticFieldBytes, type.staticFieldBytes);
                }
                else
                {
                    writer.WriteEntryArray(EntryType.TypeDescriptions_FieldIndices, new int[0]);
                    writer.WriteEntryArray(EntryType.TypeDescriptions_StaticFieldBytes, new byte[0]);
                }

                writer.WriteEntry(EntryType.TypeDescriptions_Name, type.name);
                writer.WriteEntry(EntryType.TypeDescriptions_Assembly, type.assembly);
                writer.WriteEntry(EntryType.TypeDescriptions_TypeInfoAddress, type.typeInfoAddress);
                writer.WriteEntry(EntryType.TypeDescriptions_Size, type.size);
            }

            //write managed gc handles
            for (int i = 0; i < snapshot.gcHandles.Length; ++i)
            {
                var handle = snapshot.gcHandles[i];
                writer.WriteEntry(EntryType.GCHandles_Target, handle.target);
            }

            //write managed connections
            for (int i = 0; i < snapshot.connections.Length; ++i)
            {
                var connection = snapshot.connections[i];
                writer.WriteEntry(EntryType.Connections_From, connection.from);
                writer.WriteEntry(EntryType.Connections_To, connection.to);
            }

            //write native types
            for (int i = 0; i < snapshot.nativeTypes.Length; ++i)
            {
                var nativeType = snapshot.nativeTypes[i];
                writer.WriteEntry(EntryType.NativeTypes_NativeBaseTypeArrayIndex, nativeType.nativeBaseTypeArrayIndex);
                writer.WriteEntry(EntryType.NativeTypes_Name, nativeType.name);
            }

            //write stub root reference for all native objects to point to, as the old format did not capture these
            writer.WriteEntry(EntryType.NativeRootReferences_AreaName, "Invalid Root");
            writer.WriteEntry(EntryType.NativeRootReferences_AccumulatedSize, (ulong)0);
            writer.WriteEntry(EntryType.NativeRootReferences_Id, (long)0);
            writer.WriteEntry(EntryType.NativeRootReferences_ObjectName, "Invalid Root Object");

            //write native objects
            for (int i = 0; i < snapshot.nativeObjects.Length; ++i)
            {
                var nativeObject = snapshot.nativeObjects[i];
                writer.WriteEntry(EntryType.NativeObjects_Name, nativeObject.name);
                writer.WriteEntry(EntryType.NativeObjects_InstanceId, nativeObject.instanceId);
                writer.WriteEntry(EntryType.NativeObjects_Size, (ulong)nativeObject.size);
                writer.WriteEntry(EntryType.NativeObjects_NativeTypeArrayIndex, nativeObject.nativeTypeArrayIndex);
                writer.WriteEntry(EntryType.NativeObjects_HideFlags, (UInt32)nativeObject.hideFlags);
                writer.WriteEntry(EntryType.NativeObjects_Flags, (UInt32)nativeObject.m_Flags);
                writer.WriteEntry(EntryType.NativeObjects_NativeObjectAddress, (ulong)nativeObject.nativeObjectAddress);
                writer.WriteEntry(EntryType.NativeObjects_RootReferenceId, (long)0);
            }

            //write virtual machine information
            writer.WriteEntry(EntryType.Metadata_VirtualMachineInformation, snapshot.virtualMachineInformation);
            writer.Close();

            return(true);
        }
Beispiel #6
0
        // this method is a hack that excludes native object connections to workaround an unity bug.
        // https://forum.unity.com/threads/wip-heap-explorer-memory-profiler-debugger-and-analyzer-for-unity.527949/page-2#post-3615223
        static PackedConnection[] ConnectionsFromMemoryProfilerWithoutNativeHACK(PackedMemorySnapshot snapshot, UnityEditor.MemoryProfiler.PackedMemorySnapshot source)
        {
            var managedStart = 0;
            var managedEnd   = managedStart + source.gcHandles.Length;
            var nativeStart  = managedStart + managedEnd;
            var nativeEnd    = nativeStart + source.nativeObjects.Length;
            var output       = new List <PackedConnection>(1024 * 1024);

            for (int n = 0, nend = source.connections.Length; n < nend; ++n)
            {
                if ((n % (nend / 100)) == 0)
                {
                    var progress = ((n + 1.0f) / nend) * 100;
                    snapshot.busyString = string.Format("Analyzing GCHandle Connections\n{0}/{1}, {2:F0}% done", n + 1, source.connections.Length, progress);
                }

                var connection = new PackedConnection
                {
                    from = source.connections[n].from,
                    to   = source.connections[n].to,
                };

                connection.fromKind = PackedConnection.Kind.GCHandle;
                if (connection.from >= nativeStart && connection.from < nativeEnd)
                {
                    connection.from    -= nativeStart;
                    connection.fromKind = PackedConnection.Kind.Native;
                }

                connection.toKind = PackedConnection.Kind.GCHandle;
                if (connection.to >= nativeStart && connection.to < nativeEnd)
                {
                    connection.to    -= nativeStart;
                    connection.toKind = PackedConnection.Kind.Native;
                }

                if (connection.fromKind != PackedConnection.Kind.Native)
                {
                    output.Add(connection);
                }
            }

            snapshot.header.nativeObjectFromConnectionsExcluded = true;
            Debug.LogWarning("HeapExplorer: Native object 'from' connections are excluded due workaround an Unity bug. Thus the object connections in Heap Explorer show fewer connections than actually exist.\nhttps://forum.unity.com/threads/wip-heap-explorer-memory-profiler-debugger-and-analyzer-for-unity.527949/page-2#post-3615223");
            return(output.ToArray());
        }