1、預覽&牢騷
本來標題想寫成“文本化XXX”,看上去有逼格,后來想想沒啥卵用,還可能無法準確表達文章內容,最終用了更符合我初始目的的詞 - 提取數據。
上面兩張圖應能很好的表達出這個工具的功能了 - 從Profiler中提取詳細(Detailed)內存信息,然后寫入文件。
這個工具來源于我自己工作的需要。項目中做資源管理優化時,要檢查內存中資源冗余的情況,還要對比不同場景間資源使用的差異(主要關注是否有沒被卸載的情況)。實際檢查要在Profiler的幾百條數據里找問題,Profiler是按內存大小進行排序的,查找高占用的資源非常方便,但是對這種檢查工作就非常不友好。第一次看的時候眼睛都要瞎了,一條條的看數據,甚是惡心Orm……當時就想要是能把這些數據搞到文件里,至少還能用個Ctrl+F吧。結果找了一圈也沒發現做法,只能忍著惡心完成了第一次檢查。
可喜的是,在后面做Debug封裝的時候找到了思路,感謝這個朋友的文章:解決在Unity中封裝Debug.Log后代碼行定位問題
2、實戰
這個工具的思路非常簡單:借助反射大法,調用UnityEditor里的內容
我覺得這塊內容,到這里就可以結束了……有技術含量的內容已經寫完!不過一句話作為一個小節也挺尷尬,下面介紹下如何定位到需要的代碼位置。
首先是工具,反射好用,但也得知道要反射的結果是什么。我記得上面的文章是通過打印類成員的方式來定位的,這樣確實可以,不過(開發)效率很低。我使用的是VS的一個插件,叫ReSharper,它的Assembly Explorer可以反編譯DLL,不僅能看到成員名還能看到代碼,非常方便!
接下來列舉代碼上幾個關鍵的位置,權當湊字數了(突然想起當前寫作文的感受Orm)。
- class ProfilerWindow:Profiler窗口的內容,都可以把這個類作為入口
- ProfilerWindow.m_ProfilerWindows:存儲所有當前打開的子窗口,有CPU、Memory等
- ProfilerWindow.m_MemoryListView:這個對象里,存儲了Memory Detailed采樣后的數據
- MemoryTreeListClickable.m_Root:Detailed層次結構的根節點,每個MemoryElement對象記錄了一條數據。
3、使用
這篇文章不打算給出任何工具實現的代碼,因為上面把漁都給出來了。生魚不給,最后會給條熟魚,方便快速使用。
/// <summary>
/// 提取Profiler內存數據
/// </summary>
[MenuItem("Tools/Profiler/Extract Memory")]
public static void ExtractMemory()
{
// 數據過濾器,只提取這里名稱匹配的層次
Dictionary<int, HashSet<string>> filter = new Dictionary<int, HashSet<string>>()
{
{1, new HashSet<string>() {"Assets",}}, //"Other", "Not Saved"
{2, new HashSet<string>()
{
"SerializedFile",
"Texture2D",
}
},
};
MemoryElement root = ProfilerWindow.GetMemoryDetailRoot(filter);
if (null != root)
{
string path = Path.Combine(OutputPath, "Mem Detailed.txt");
using (StreamWriter writer = new StreamWriter(path))
{
ProfilerWindow.WriteMemoryDetail(writer, root);
}
}
Debug.Log("Save Memory Datas Finish.");
}
我工具里對數據做了幾處小處理:
- 排序:我使用節點名稱的字典序排序的,這樣輸出后,查找冗余資源會方便很多;資源對比,借助BeyondCompare也很方便。
- 過濾:添加了簡單的過濾條件,就是上面代碼中的filter。實際項目中Profiler數據達到幾W條很輕松,但是通常并不需要關注全部的,只要把大頭解決就好。
使用步驟:
1)打開Profiler - Memory - Detailed,自己點Take Sample
2)數據出來后,點Tools/Profiler/Extract Memory按鈕
這是我編譯好的DLL庫(熟魚),可以直接拿來用(XML是注釋文檔)
EditorToolkit - ExtractMemory.dll
EditorToolkit - ExtractMemory.xml