本文也叫跟著 Stephen Toub 大佬學性能優化系列,這是我從 Stephen Toub 大佬給 WPF 框架做性能優化學到的知識,在熱路徑下,也就是頻繁呼叫的模塊,如果呼叫了委托的 GetInvocationList 方法,那么將視委托的大小,每次創建不同大小的新陣列物件,而在頻繁呼叫的模塊,將會創建大量的物件
如以下代碼的一個委托,當然對于事件來說也是如此
Action action = Foo;
for (int i = 0; i < 10; i++)
{
action += Foo;
}
static void Foo()
{
}
如果呼叫了 action 的 GetInvocationList 方法,那么在每次呼叫都會申請一些記憶體,如使用以下代碼進行測驗
for (int i = 0; i < 100; i++)
{
var beforeAllocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
var invocationList = action.GetInvocationList();
var afterAllocatedBytesForCurrentThread = GC.GetAllocatedBytesForCurrentThread();
Console.WriteLine(afterAllocatedBytesForCurrentThread - beforeAllocatedBytesForCurrentThread);
}
上面代碼的 GetAllocatedBytesForCurrentThread 是一個放在 GC 層面的方法,可以用來獲取當前執行緒分配過的記憶體大小,這是一個用來輔助除錯的方法,詳細請看 dotnet 使用 GC.GetAllocatedBytesForCurrentThread 獲取當前執行緒分配過的記憶體大小
可以看到運行時的控制臺輸出如下
312
112
112
112
112
112
112
112
112
112
112
112
// 不水了
這是因為在底層的實作,呼叫 GetInvocationList 方法的代碼如下
public override sealed Delegate[] GetInvocationList()
{
Delegate[] delegateArray;
if (!(this._invocationList is object[] invocationList))
{
delegateArray = new Delegate[1]{ (Delegate) this };
}
else
{
delegateArray = new Delegate[(int) this._invocationCount];
for (int index = 0; index < delegateArray.Length; ++index)
delegateArray[index] = (Delegate) invocationList[index];
}
return delegateArray;
}
可以看到每次都需要重新申請陣列,然后給定陣列里面的元素,如果在呼叫頻繁的模塊里面,不斷呼叫 GetInvocationList 方法,將會有一定的性能損耗,如在 WPF 的移動滑鼠等邏輯里面
一個優化的方法是,如果指定的委托或事件的加等次數比呼叫 GetInvocationList 的次數少,如 WPF 的 PreNotifyInput 等事件,此時可以通過在加等的時候快取起來,這樣后續的呼叫就不需要重新分配記憶體
以上優化的細節請看 Avoid calling GetInvocationList on hot paths by stephentoub · Pull Request #4736 · dotnet/wpf
本文所有代碼放在 github 和 gitee 歡迎訪問
可以通過如下方式獲取本文的源代碼,先創建一個空檔案夾,接著使用命令列 cd 命令進入此空檔案夾,在命令列里面輸入以下代碼,即可獲取到本文的代碼
git init
git remote add origin https://gitee.com/lindexi/lindexi_gd.git
git pull origin 6ed312e74e286d581e3d609ed555447474259ae4
以上使用的是 gitee 的源,如果 gitee 不能訪問,請替換為 github 的源
git remote remove origin
git remote add origin https://github.com/lindexi/lindexi_gd.git
獲取代碼之后,進入 FairhojafallJeeleefuyi 檔案夾
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/288726.html
標籤:.NET技术
上一篇:NPOI 設定背景顏色
下一篇:WPF 勾選劃線
