少年修仙传客户端基础资源
client_Wu Xijin
2019-01-16 d53a782e2fd91ffc47dad0dd5a080ee451a351b7
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MemoryProfilerWindow;
using UnityEditor.MemoryProfiler;
using UnityEngine;
 
namespace MemoryProfilerWindow
{
    class ShortestPathToRootFinder
    {
        private readonly CrawledMemorySnapshot _snapshot;
 
        public ShortestPathToRootFinder(CrawledMemorySnapshot snapshot)
        {
            _snapshot = snapshot;
        }
 
        public ThingInMemory[] FindFor(ThingInMemory thing)
        {
            var seen = new HashSet<ThingInMemory>();
            var queue = new Queue<List<ThingInMemory>>();
            queue.Enqueue(new List<ThingInMemory> { thing});
 
            while (queue.Any())
            {
                var pop = queue.Dequeue();
                var tip = pop.Last();
 
                string reason;
                if (IsRoot(tip, out reason))
                    return pop.ToArray();
 
                foreach (var next in tip.referencedBy)
                {
                    if (seen.Contains(next))
                        continue;
                    seen.Add(next);
                    var dupe = new List<ThingInMemory>(pop) {next};
                    queue.Enqueue(dupe);
                }
            }
            return null;
        }
 
        public 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;
 
            var 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 bool IsGameObject(int classID)
        {
            return _snapshot.nativeTypes[classID].name == "GameObject";
        }
 
        private bool IsAssetBundle(int classID)
        {
            return _snapshot.nativeTypes[classID].name == "AssetBundle";
        }
 
        private bool IsComponent(int classID)
        {
            var packedNativeType = _snapshot.nativeTypes[classID];
 
            if (packedNativeType.name == "Component")
                return true;
 
#if UNITY_5_6_OR_NEWER
            var baseClassID = packedNativeType.nativeBaseTypeArrayIndex;
#else
            var baseClassID = packedNativeType.baseClassId;
#endif
 
            return baseClassID != -1 && IsComponent(baseClassID);
        }
    }
}