Example #1
0
        /// <summary>
        ///
        /// </summary>
        /// <param name="toReplace"></param>
        public static void ReplaceModelFromFile(HSD_JOBJ toReplace)
        {
            var f = Tools.FileIO.OpenFile(IOManager.GetModelImportFileFilter());

            if (f != null)
            {
                var settings = new ModelImportSettings();
                using (PropertyDialog d = new PropertyDialog("Model Import Options", settings))
                {
                    if (d.ShowDialog() == System.Windows.Forms.DialogResult.OK)
                    {
                        ImportSettings ioSettings = new ImportSettings()
                        {
                            FlipUVs          = settings.FlipUVs,
                            FlipWindingOrder = !settings.FlipFaces,
                            SmoothNormals    = settings.SmoothNormals,
                            Triangulate      = true,
                            //WeightLimit = true,
                        };

                        ModelImporter imp = new ModelImporter(f, settings, ioSettings);

                        using (ProgressBarDisplay pb = new ProgressBarDisplay(imp))
                        {
                            pb.DoWork();
                            pb.ShowDialog();
                        }

                        var newroot = imp.NewModel;

                        toReplace._s.SetFromStruct(newroot._s);
                    }
                }
            }
        }
 internal FrameSetupData(int minFrame, int maxFrame, int filterDepth, List <string> filterThreads)
 {
     progressBar   = new ProgressBarDisplay();
     firstFrame    = minFrame;
     lastFrame     = maxFrame;
     analyzer      = new ProfileAnalyzer(progressBar);
     profileData   = analyzer.PullFromProfiler(minFrame, maxFrame);
     depthFilter   = filterDepth;
     threadFilters = filterThreads;
 }
Example #3
0
        public void SetupView(ulong rowMemorySize)
        {
            ProgressBarDisplay.ShowBar("Setup memory map diff view ");

            m_BytesInRow = rowMemorySize;

            CreateGroups();

            SetupGroups();

            ProgressBarDisplay.ClearBar();
        }
Example #4
0
        void CreateGroups( )
        {
            m_Groups.Clear();

            ProgressBarDisplay.UpdateProgress(0.0f, "Create groups ...");

            int metaRegions = 0;

            while (m_SnapshotMemoryRegion[metaRegions].AddressBegin == 0 && m_SnapshotMemoryRegion[metaRegions].AddressBegin == m_SnapshotMemoryRegion[metaRegions].AddressEnd)
            {
                metaRegions++;
            }

            int   groupIdx          = 0;
            ulong groupAddressBegin = m_SnapshotMemoryRegion[metaRegions].AddressBegin;
            ulong groupAddressEnd   = groupAddressBegin;

            for (int i = metaRegions; i < m_SnapshotMemoryRegion.Length; ++i)
            {
                if (i % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)i / (float)m_SnapshotMemoryRegion.Length);
                }

                if (m_SnapshotMemoryRegion[i].Type == RegionType.VirtualMemory && !GetDisplayElement(DisplayElements.VirtualMemory))
                {
                    continue;
                }

                ulong addressBegin = m_SnapshotMemoryRegion[i].AddressBegin;
                ulong addressEnd   = m_SnapshotMemoryRegion[i].AddressEnd;

                if ((addressBegin > groupAddressEnd) && (addressBegin / m_BytesInRow) > (groupAddressEnd / m_BytesInRow) + 1)
                {
                    AddGroup(groupAddressBegin, groupAddressEnd);
                    groupAddressBegin = addressBegin;
                    groupAddressEnd   = addressEnd;
                    groupIdx++;
                }
                else
                {
                    groupAddressEnd = Math.Max(groupAddressEnd, addressEnd);
                }

                m_SnapshotMemoryRegion[i].Group = groupIdx;
            }

            AddGroup(groupAddressBegin, groupAddressEnd);

            ProgressBarDisplay.UpdateProgress(1.0f);
        }
        public void Setup(CachedSnapshot snapshot)
        {
            m_Snapshot = snapshot;

            ProgressBarDisplay.ShowBar("Setup memory map");

            SetupSortedData();

            SetupRegions();

            CreateGroups();

            SetupGroups();

            ProgressBarDisplay.ClearBar();
        }
Example #6
0
        public void Setup(CachedSnapshot snapshotA, CachedSnapshot snapshotB)
        {
            m_Snapshots[0] = snapshotA;
            m_Snapshots[1] = snapshotB;

            ProgressBarDisplay.ShowBar("Setup memory map diff");

            SetupSortedData();

            SetupRegions();

            CreateGroups();

            SetupGroups();

            ProgressBarDisplay.ClearBar();
        }
Example #7
0
        protected void PrepareSortedData(CachedSnapshot.ISortedEntriesCache[] caches)
        {
            ProgressBarDisplay.UpdateProgress(0.0f, "Sorting data ...");

            long entriesCount     = 0;
            long entriesProcessed = 0;

            for (int i = 0; i < caches.Length; ++i)
            {
                entriesCount += caches[i].Count;
            }

            for (int i = 0; i < caches.Length; ++i)
            {
                CachedSnapshot.ISortedEntriesCache cache = caches[i];
                cache.Preload();
                entriesProcessed += cache.Count;
                ProgressBarDisplay.UpdateProgress((float)((100 * entriesProcessed) / entriesCount) / 100.0f);
            }
        }
Example #8
0
        void SetupGroups( )
        {
            ProgressBarDisplay.UpdateProgress(0.0f, "Setup groups ...");

            for (Int32 snapshotIdx = 0; snapshotIdx < 2; ++snapshotIdx)
            {
                CachedSnapshot snapshot = m_Snapshots[snapshotIdx];

                int managedObjectsOffset = 0;
                int managedObjectsCount  = snapshot.SortedManagedObjects.Count;

                int nativeAllocationsOffset = 0;
                int nativeAllocationsCount  = snapshot.SortedNativeAllocations.Count;


                int nativeObjectsOffset = 0;
                int nativeObjectsCount  = snapshot.SortedNativeObjects.Count;

                m_GroupsMangedObj[snapshotIdx].Clear();
                m_GroupsNativeAlloc[snapshotIdx].Clear();
                m_GroupsNativeObj[snapshotIdx].Clear();

                EntryRange range;

                for (int i = 0; i < m_Groups.Count; ++i)
                {
                    if (i % 1000 == 0)
                    {
                        ProgressBarDisplay.UpdateProgress((float)i / (float)m_Groups.Count);
                    }

                    // Assigning Managed Objects Range
                    while (managedObjectsOffset < managedObjectsCount && m_Groups[i].AddressBegin > snapshot.SortedManagedObjects.Address(managedObjectsOffset))
                    {
                        managedObjectsOffset++;
                    }

                    range.Begin = managedObjectsOffset;

                    while (managedObjectsOffset < managedObjectsCount && snapshot.SortedManagedObjects.Address(managedObjectsOffset) < m_Groups[i].AddressEnd)
                    {
                        managedObjectsOffset++;
                    }

                    range.End = managedObjectsOffset;

                    m_GroupsMangedObj[snapshotIdx].Add(range);

                    // Assigning Native Allocation Range
                    while (nativeAllocationsOffset < nativeAllocationsCount && m_Groups[i].AddressBegin > snapshot.SortedNativeAllocations.Address(nativeAllocationsOffset))
                    {
                        nativeAllocationsOffset++;
                    }

                    range.Begin = nativeAllocationsOffset;

                    while (nativeAllocationsOffset < nativeAllocationsCount && snapshot.SortedNativeAllocations.Address(nativeAllocationsOffset) < m_Groups[i].AddressEnd)
                    {
                        nativeAllocationsOffset++;
                    }

                    range.End = nativeAllocationsOffset;

                    m_GroupsNativeAlloc[snapshotIdx].Add(range);

                    // Assigning Native Objects Range
                    while (nativeObjectsOffset < nativeObjectsCount && m_Groups[i].AddressBegin > snapshot.SortedNativeObjects.Address(nativeObjectsOffset))
                    {
                        nativeObjectsOffset++;
                    }

                    range.Begin = nativeObjectsOffset;

                    while (nativeObjectsOffset < nativeObjectsCount && snapshot.SortedNativeObjects.Address(nativeObjectsOffset) < m_Groups[i].AddressEnd)
                    {
                        nativeObjectsOffset++;
                    }

                    range.End = nativeObjectsOffset;

                    m_GroupsNativeObj[snapshotIdx].Add(range);
                }
            }

            ProgressBarDisplay.UpdateProgress(1.0f);
        }
Example #9
0
        void SetupRegions()
        {
            ProgressBarDisplay.UpdateProgress(0.0f, "Flushing regions ...");

            uint regionCount = 0;

            for (int snapshotIdx = 0; snapshotIdx < m_Snapshots.Length; ++snapshotIdx)
            {
                regionCount += m_Snapshots[snapshotIdx].nativeMemoryRegions.Count + m_Snapshots[snapshotIdx].managedHeapSections.Count + m_Snapshots[snapshotIdx].managedStacks.Count;
            }

            m_SnapshotMemoryRegion = new DiffMemoryRegion[regionCount];

            int regionIndex = 0;

            int offset = 0;

            uint processed = 0;

            for (int i = 0; i != m_Snapshots[0].SortedNativeRegionsEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                DiffMemoryRegion region = CreateNativeRegion(regionIndex, m_Snapshots[0], i);
                region.m_Snapshot = PresenceInSnapshots.First;
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            int offsetMax = regionIndex;

            for (int i = 0; i != m_Snapshots[1].SortedNativeRegionsEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong  addr = m_Snapshots[1].SortedNativeRegionsEntries.Address(i);
                ulong  size = (ulong)m_Snapshots[1].SortedNativeRegionsEntries.Size(i);
                string name = m_Snapshots[1].SortedNativeRegionsEntries.Name(i);

                while (offset < offsetMax && m_SnapshotMemoryRegion[offset].AddressBegin < addr)
                {
                    offset++;
                }

                for (int j = offset; j < offsetMax && m_SnapshotMemoryRegion[j].AddressBegin == addr; ++j)
                {
                    if (m_SnapshotMemoryRegion[j].Name == name && m_SnapshotMemoryRegion[j].Size == size)
                    {
                        m_SnapshotMemoryRegion[j].m_Snapshot |= PresenceInSnapshots.Second;
                        name = null;
                        break;
                    }
                }

                if (name != null)
                {
                    DiffMemoryRegion region = CreateNativeRegion(regionIndex, m_Snapshots[1], i);
                    region.m_Snapshot = PresenceInSnapshots.Second;
                    m_SnapshotMemoryRegion[regionIndex++] = region;
                }
            }

            offset = regionIndex;

            for (int i = 0; i != m_Snapshots[0].SortedManagedHeapEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                DiffMemoryRegion region = CreateManagedHeapRegion(regionIndex, m_Snapshots[0], i);
                region.m_Snapshot = PresenceInSnapshots.First;
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            offsetMax = regionIndex;

            for (int i = 0; i != m_Snapshots[1].SortedManagedHeapEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong addr = m_Snapshots[1].SortedManagedHeapEntries.Address(i);
                ulong size = (ulong)m_Snapshots[1].SortedManagedHeapEntries.Size(i);

                while (offset < offsetMax && m_SnapshotMemoryRegion[offset].AddressBegin < addr)
                {
                    offset++;
                }

                for (int j = offset; j < offsetMax && m_SnapshotMemoryRegion[j].AddressBegin == addr; ++j)
                {
                    if (m_SnapshotMemoryRegion[j].Size == size)
                    {
                        m_SnapshotMemoryRegion[j].m_Snapshot |= PresenceInSnapshots.Second;
                        addr = size = 0;
                        break;
                    }
                }

                if (addr != 0)
                {
                    DiffMemoryRegion region = CreateManagedHeapRegion(regionIndex, m_Snapshots[1], i);
                    region.m_Snapshot = PresenceInSnapshots.Second;
                    m_SnapshotMemoryRegion[regionIndex++] = region;
                }
            }


            offset = regionIndex;

            for (int i = 0; i != m_Snapshots[0].SortedManagedStacksEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                DiffMemoryRegion region = CreateManagedStackRegion(regionIndex, m_Snapshots[0], i);
                region.m_Snapshot = PresenceInSnapshots.First;
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            offsetMax = regionIndex;

            for (int i = 0; i != m_Snapshots[1].SortedManagedStacksEntries.Count; ++i)
            {
                if (processed++ % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)processed / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong addr = m_Snapshots[1].SortedManagedStacksEntries.Address(i);
                ulong size = (ulong)m_Snapshots[1].SortedManagedStacksEntries.Size(i);

                while (offset < offsetMax && m_SnapshotMemoryRegion[offset].AddressBegin < addr)
                {
                    offset++;
                }

                for (int j = offset; j < offsetMax && m_SnapshotMemoryRegion[j].AddressBegin == addr; ++j)
                {
                    if (m_SnapshotMemoryRegion[j].Size == size)
                    {
                        m_SnapshotMemoryRegion[j].m_Snapshot |= PresenceInSnapshots.Second;
                        addr = size = 0;
                        break;
                    }
                }

                if (addr != 0)
                {
                    DiffMemoryRegion region = CreateManagedStackRegion(regionIndex, m_Snapshots[1], i);
                    region.m_Snapshot = PresenceInSnapshots.Second;
                    m_SnapshotMemoryRegion[regionIndex++] = region;
                }
            }


            ProgressBarDisplay.UpdateProgress(0.0f, "Sorting regions ..");

            Array.Resize(ref m_SnapshotMemoryRegion, regionIndex);

            Array.Sort(m_SnapshotMemoryRegion, delegate(MemoryRegion a, MemoryRegion b)
            {
                int result = a.AddressBegin.CompareTo(b.AddressBegin);

                if (result == 0)
                {
                    result = -a.AddressEnd.CompareTo(b.AddressEnd);
                }

                return(result);
            }
                       );
        }
        void SetupRegions()
        {
            ProgressBarDisplay.UpdateProgress(0.0f, "Flushing regions ...");

            int regionIndex = 0;

            m_SnapshotMemoryRegion = new MemoryRegion[m_Snapshot.nativeMemoryRegions.Count + m_Snapshot.managedHeapSections.Count + m_Snapshot.managedStacks.Count];

            for (int i = 0; i != m_Snapshot.nativeMemoryRegions.Count; ++i)
            {
                if (regionIndex % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)regionIndex / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong  start = m_Snapshot.nativeMemoryRegions.addressBase[i];
                ulong  size  = (ulong)m_Snapshot.nativeMemoryRegions.addressSize[i];
                string name  = m_Snapshot.nativeMemoryRegions.memoryRegionName[i];

                MemoryRegion region;
                if (name.Contains("Virtual Memory"))
                {
                    region             = new MemoryRegion(RegionType.VirtualMemory, start, size, name);
                    region.ColorRegion = m_ColorNative[(int)EntryColors.VirtualMemory];
                }
                else
                {
                    region             = new MemoryRegion(RegionType.Native, start, size, name);
                    region.ColorRegion = m_ColorNative[(int)EntryColors.Region];
                }

                region.ColorRegion = new Color32(region.ColorRegion.r, region.ColorRegion.g, region.ColorRegion.b, (byte)(1 + regionIndex % 255));
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            for (int i = 0; i != m_Snapshot.managedHeapSections.Count; ++i)
            {
                if (regionIndex % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)regionIndex / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong  start = m_Snapshot.managedHeapSections.startAddress[i];
                ulong  size  = (ulong)m_Snapshot.managedHeapSections.bytes[i].Length;
                string name  = string.Format("Heap Sections {0}", i);

                MemoryRegion region = new MemoryRegion(RegionType.Managed, start, size, name);
                region.ColorRegion = m_ColorManaged[(int)EntryColors.Region];
                region.ColorRegion = new Color32(region.ColorRegion.r, region.ColorRegion.g, region.ColorRegion.b, (byte)(1 + regionIndex % 255));
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            ProgressBarDisplay.UpdateProgress((float)regionIndex / (float)m_SnapshotMemoryRegion.Length);

            for (int i = 0; i != m_Snapshot.managedStacks.Count; ++i)
            {
                if (regionIndex % 10000 == 0)
                {
                    ProgressBarDisplay.UpdateProgress((float)regionIndex / (float)m_SnapshotMemoryRegion.Length);
                }

                ulong  start = m_Snapshot.managedStacks.startAddress[i];
                ulong  size  = (ulong)m_Snapshot.managedStacks.bytes[i].Length;
                string name  = string.Format("Stack Sections {0}", i);

                MemoryRegion region = new MemoryRegion(RegionType.ManagedStack, start, size, name);
                region.ColorRegion = m_ColorManagedStack[(int)EntryColors.Region];
                region.ColorRegion = new Color32(region.ColorRegion.r, region.ColorRegion.g, region.ColorRegion.b, (byte)(1 + regionIndex % 255));
                m_SnapshotMemoryRegion[regionIndex++] = region;
            }

            ProgressBarDisplay.UpdateProgress((float)regionIndex / (float)m_SnapshotMemoryRegion.Length);

            ProgressBarDisplay.UpdateProgress(0.0f, "Sorting regions ...");

            Array.Sort(m_SnapshotMemoryRegion, delegate(MemoryRegion a, MemoryRegion b)
            {
                int result = a.AddressBegin.CompareTo(b.AddressBegin);

                if (result == 0)
                {
                    result = -a.AddressEnd.CompareTo(b.AddressEnd);
                }

                return(result);
            }
                       );

            ProgressBarDisplay.UpdateProgress(1.0f);
        }
Example #11
0
    private void LoadAll()
    {
        m_IsReady = false;
        try {
            foreach (var filePath in m_List)
            {
                if (File.Exists(filePath))
                {
                    try {
                        Debug.LogFormat("Loading \"{0}\"", filePath);
                        var rawSnapshot = Unity.MemoryProfilerForExtension.Editor.Format.QueriedMemorySnapshot.Load(filePath);
                        //var rawSnapshot = UnityEditor.Profiling.Memory.Experimental.PackedMemorySnapshot.Load(filePath);
                        if (null == rawSnapshot)
                        {
                            Debug.LogErrorFormat("MemoryProfiler: Unrecognized memory snapshot format '{0}'.", filePath);
                        }
                        Debug.LogFormat("Completed loading \"{0}\"", filePath);

                        Debug.LogFormat("Crawling \"{0}\"", filePath);
                        ProgressBarDisplay.ShowBar(string.Format("Opening snapshot: {0}", System.IO.Path.GetFileNameWithoutExtension(filePath)));

                        var cachedSnapshot = new CachedSnapshot(rawSnapshot);
                        using (s_CrawlManagedData.Auto()) {
                            var crawling = Crawler.Crawl(cachedSnapshot);
                            crawling.MoveNext(); //start execution

                            var   status          = crawling.Current as EnumerationStatus;
                            float progressPerStep = 1.0f / status.StepCount;
                            while (crawling.MoveNext())
                            {
                                ProgressBarDisplay.UpdateProgress(status.CurrentStep * progressPerStep, status.StepStatus);
                            }
                        }
                        ProgressBarDisplay.ClearBar();
                        var rawSchema = new RawSchema();
                        rawSchema.SetupSchema(cachedSnapshot, new ObjectDataFormatter());
                        var managedObjcts = rawSchema.GetTableByName("AllManagedObjects") as ObjectListTable;
                        var nativeObjects = rawSchema.GetTableByName("AllNativeObjects") as ObjectListTable;
                        Debug.LogFormat("Completed crawling \"{0}\"", filePath);

                        Debug.LogFormat("Saving \"{0}\"", filePath);
                        var path     = Path.GetDirectoryName(filePath);
                        var snapName = Path.GetFileNameWithoutExtension(filePath);

                        string exportPath1 = Path.Combine(path, snapName + "_MANAGEDHEAP_SnapshotExport_" + CsLibrary.DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv");
                        if (!String.IsNullOrEmpty(exportPath1))
                        {
                            System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath1);
                            sw.WriteLine("Managed_Objects,Size,Address");
                            int ct = cachedSnapshot.SortedManagedHeapEntries.Count;
                            for (int i = 0; i < ct; i++)
                            {
                                var size = cachedSnapshot.SortedManagedHeapEntries.Size(i);
                                var addr = cachedSnapshot.SortedManagedHeapEntries.Address(i);
                                sw.WriteLine("Managed," + size + "," + addr);
                                ResourceProcessor.Instance.DisplayProgressBar("write managed heap ...", i, ct);
                            }
                            sw.Flush();
                            sw.Close();
                        }

                        string exportPath2 = Path.Combine(path, snapName + "_MANAGED_SnapshotExport_" + CsLibrary.DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv");
                        if (!String.IsNullOrEmpty(exportPath2))
                        {
                            m_ManagedGroups.Clear();
                            System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath2);
                            sw.WriteLine("Index,Type,RefCount,Size,Address");

                            int ct = cachedSnapshot.SortedManagedObjects.Count;
                            for (int i = 0; i < ct; i++)
                            {
                                var size = cachedSnapshot.SortedManagedObjects.Size(i);
                                var addr = cachedSnapshot.SortedManagedObjects.Address(i);
                                ManagedObjectInfo objInfo;
                                int    index    = -1;
                                int    refCount = 0;
                                string typeName = string.Empty;
                                if (cachedSnapshot.CrawledData.MangedObjectIndexByAddress.TryGetValue(addr, out index))
                                {
                                    objInfo  = cachedSnapshot.CrawledData.ManagedObjects[index];
                                    index    = objInfo.ManagedObjectIndex;
                                    refCount = objInfo.RefCount;
                                    if (objInfo.ITypeDescription >= 0 && objInfo.ITypeDescription < cachedSnapshot.typeDescriptions.Count)
                                    {
                                        typeName = cachedSnapshot.typeDescriptions.typeDescriptionName[objInfo.ITypeDescription];
                                    }
                                }
                                sw.WriteLine("" + index + ",\"" + typeName + "\"," + refCount + "," + size + "," + addr);

                                ManagedGroupInfo info;
                                if (m_ManagedGroups.TryGetValue(typeName, out info))
                                {
                                    ++info.Count;
                                    info.Size += size;
                                }
                                else
                                {
                                    string g  = string.Empty;
                                    int    si = typeName.IndexOf('.');
                                    if (si > 0)
                                    {
                                        g = typeName.Substring(0, si);
                                        if (!s_ManagedGroupNames.Contains(g))
                                        {
                                            g = string.Empty;
                                        }
                                    }
                                    info = new ManagedGroupInfo {
                                        Group = g, Type = typeName, Count = 1, Size = size
                                    };
                                    m_ManagedGroups.Add(typeName, info);
                                }
                                if (i % 1000 == 0)
                                {
                                    ResourceProcessor.Instance.DisplayProgressBar("write managed objects ...", i, ct);
                                }
                            }
                            sw.Flush();
                            sw.Close();

                            string dir       = Path.GetDirectoryName(exportPath2);
                            string fn        = Path.GetFileNameWithoutExtension(exportPath2);
                            string gpath     = Path.Combine(dir, fn + "_groups.csv");
                            var    lastGroup = "A000000";
                            using (var outsw = new StreamWriter(gpath)) {
                                outsw.WriteLine("group,type,count,size");
                                int curCt   = 0;
                                int totalCt = m_ManagedGroups.Count;
                                foreach (var pair in m_ManagedGroups)
                                {
                                    var info = pair.Value;
                                    var g    = info.Group;
                                    if (!string.IsNullOrEmpty(lastGroup) && string.IsNullOrEmpty(info.Group))
                                    {
                                        g = lastGroup + "__";
                                    }
                                    if (!string.IsNullOrEmpty(info.Group))
                                    {
                                        lastGroup = info.Group;
                                    }
                                    outsw.WriteLine("\"{0}\",\"{1}\",{2},{3}", g, info.Type, info.Count, info.Size);
                                    if (curCt % 100 == 0)
                                    {
                                        ResourceProcessor.Instance.DisplayProgressBar("write managed object group ...", curCt, totalCt);
                                    }
                                    ++curCt;
                                }
                            }
                            string gpath2 = Path.Combine(dir, fn + "_groups_forcmp.csv");
                            using (var outsw = new StreamWriter(gpath2)) {
                                outsw.WriteLine("type,count,size");
                                int curCt   = 0;
                                int totalCt = m_ManagedGroups.Count;
                                foreach (var pair in m_ManagedGroups)
                                {
                                    var info = pair.Value;
                                    outsw.WriteLine("\"{0}\",{1},{2}", info.Type, info.Count, info.Size);
                                    if (curCt % 100 == 0)
                                    {
                                        ResourceProcessor.Instance.DisplayProgressBar("write managed object group for cmp ...", curCt, totalCt);
                                    }
                                    ++curCt;
                                }
                            }
                        }

                        string exportPath = Path.Combine(path, snapName + "_NATIVE_SnapshotExport_" + CsLibrary.DateTime.Now.ToString("dd_MM_yyyy_hh_mm_ss") + ".csv");
                        if (!String.IsNullOrEmpty(exportPath))
                        {
                            m_NativeGroups.Clear();
                            System.IO.StreamWriter sw = new System.IO.StreamWriter(exportPath);
                            sw.WriteLine("Index,Name,Type,RefCount,InstanceID,Size,Address");
                            int ct = cachedSnapshot.SortedNativeObjects.Count;
                            for (int i = 0; i < ct; i++)
                            {
                                var size       = cachedSnapshot.SortedNativeObjects.Size(i);
                                var addr       = cachedSnapshot.SortedNativeObjects.Address(i);
                                var name       = cachedSnapshot.SortedNativeObjects.Name(i);
                                var refCount   = cachedSnapshot.SortedNativeObjects.Refcount(i);
                                var instanceId = cachedSnapshot.SortedNativeObjects.InstanceId(i);
                                int index;
                                if (!cachedSnapshot.nativeObjects.instanceId2Index.TryGetValue(instanceId, out index))
                                {
                                    index = -1;
                                }
                                var    nativeTypeIndex = cachedSnapshot.SortedNativeObjects.NativeTypeArrayIndex(i);
                                string typeName        = string.Empty;
                                if (nativeTypeIndex >= 0 && nativeTypeIndex < cachedSnapshot.nativeTypes.Count)
                                {
                                    typeName = cachedSnapshot.nativeTypes.typeName[nativeTypeIndex];
                                }

                                sw.WriteLine("" + index + ",\"" + name + "\",\"" + typeName + "\"," + refCount + "," + instanceId + "," + size + "," + addr);

                                NativeGroupInfo info;
                                if (m_NativeGroups.TryGetValue(typeName, out info))
                                {
                                    ++info.Count;
                                    info.Size += size;
                                }
                                else
                                {
                                    info = new NativeGroupInfo {
                                        Type = typeName, Count = 1, Size = size
                                    };
                                    m_NativeGroups.Add(typeName, info);
                                }
                                if (i % 100 == 0)
                                {
                                    ResourceProcessor.Instance.DisplayProgressBar("write native objects ...", i, ct);
                                }
                            }
                            sw.Flush();
                            sw.Close();

                            string dir   = Path.GetDirectoryName(exportPath);
                            string fn    = Path.GetFileNameWithoutExtension(exportPath);
                            string gpath = Path.Combine(dir, fn + "_groups.csv");
                            using (var outsw = new StreamWriter(gpath)) {
                                outsw.WriteLine("type,count,size");
                                int curCt   = 0;
                                int totalCt = m_NativeGroups.Count;
                                foreach (var pair in m_NativeGroups)
                                {
                                    var info = pair.Value;
                                    outsw.WriteLine("\"{0}\",{1},{2}", info.Type, info.Count, info.Size);
                                    ResourceProcessor.Instance.DisplayProgressBar("write native object group ...", curCt, totalCt);
                                    ++curCt;
                                }
                            }
                        }

                        Debug.LogFormat("Completed saving \"{0}\"", filePath);
                    }
                    catch (Exception ex) {
                        UnityEngine.Debug.LogErrorFormat("file {0} exception {1}\n{2}", filePath, ex.Message, ex.StackTrace);
                    }
                }
            }
            EditorUtility.ClearProgressBar();
        }
        finally {
            m_IsReady = true;
        }
    }