C# 使用綁定句柄來減少進程的記憶體耗用
許多應用程式中,綁定了一組類型(Type)或類型成員(從MemberInfo派生),並將這些物件保存在某種形式的一個集合中。以後,會搜尋這個集合,找出特定的對象,然後呼叫這個對象。這是一個很好的機制,但有個小問題:Type和MemberInfo衍生的物件需要大量的記憶體。如果一個應用程式容納了太多這樣的類,但只是偶爾用一下它們,應用程式的記憶體就會急劇增長,對應用程式的效能產生影響。
在內部,CLR用一種更精簡的形式來表示這種資訊。 CLR之所以為應用程式建立這些對象,只是為了簡化開發人員的工作。 CLR在運作時並不需要這些大物件。如果需要快取大量Type和MemberInfo派生對象,開發人員可以使用運行時句柄(runtime handle)來取代對象,從而減少工作集(佔用的記憶體)。 FCL定義了3個運行時句柄類型(都在System命名空間),RuntimeTypeHandle,RuntimeFieldHandle,RumtimeMethodHandle。三個類型都是值類型,他們只包含了一個字段,也就是一個IntPtr;這樣一來,這些類型的實例就相當省內存。 ItPtr字段是一個句柄,它引用了AppDomain的Loader堆中的一個類型,字段或方法。轉換方法:
Type→RuntimeTypeHandle,透過查詢Type的只讀欄位屬性TypeHandle。
RuntimeTypeHandle→Type,透過呼叫Type的靜態方法GetTypeFromHanlde。
FieldInfo→RuntimeFieldHandle,透過查詢FieldInfo的實例只讀欄位FieldHandle。
RuntimeFieldHandle→FieldInfo,透過呼叫FieldInfo的靜態方法GetFieldFromHandle。
MethodInfo→RuntimeMethodHandle,透過查詢MethodInof的實例只讀欄位MethodHandle。
RuntimeMethodHandle→MethodInfo,透過呼叫MethodInfo的靜態方法GetMethodFromHandle。
下面的範例取得許多的MethodInfo對象,把它們轉換成RuntimeMethodHandle實例,並示範轉換前後的記憶體差異。
private void UseRuntimeHandleToReduceMemory() { Show("Before doing anything");//从MSCorlib.dll中地所有方法构建methodInfos 对象缓存 List<MethodBase> methodInfos = new List<MethodBase>(); foreach (Type t in typeof(object).Assembly.GetExportedTypes()) { if (t.IsGenericType) continue; MethodBase[] mbs = t.GetMethods(c_bf); methodInfos.AddRange(mbs); } //显示当绑定所有方法之后,方法的个数和堆的大小 Console.WriteLine("# of Methods={0:###,###}", methodInfos.Count); Show("After building cache of MethodInfo objects");//为所有MethodInfo对象构建RuntimeMethodHandle缓存 List<RuntimeMethodHandle> methodHandles = new List<RuntimeMethodHandle>(); methodHandles = methodInfos.ConvertAll<RuntimeMethodHandle>(m => m.MethodHandle); Show("Holding MethodInfo and RuntimeMethodHandle"); GC.KeepAlive(methodHandles);//阻止缓存被过早垃圾回收 methodInfos = null;//现在允许缓存垃圾回收 Show("After freeing MethodInfo objects"); methodInfos = methodHandles.ConvertAll<MethodBase>(r => MethodBase.GetMethodFromHandle(r)); Show("Size of heap after re-creating methodinfo objects"); GC.KeepAlive(methodHandles);//阻止缓存被过早垃圾回收 GC.KeepAlive(methodInfos);//阻止缓存被过早垃圾回收 methodInfos = null;//现在允许缓存垃圾回收 methodHandles = null;//现在允许缓存垃圾回收 Show("after freeing MethodInfo and MethodHandle objects"); }
結果如下:
Heap Size = 114,788 - Before doing anything # of Methods=10,003Heap Size = 2,205,652 - After building cache of MethodInfo objects Heap Size = 2,245,744 - Holding MethodInfo and RuntimeMethodHandle Heap Size = 2,171,976 - After freeing MethodInfo objects Heap Size = 2,327,516 - Size of heap after re-creating methodinfo objects Heap Size = 247,028 - after freeing MethodInfo and MethodHandle objects
本文整理自《NET CLR via C#》
作者:jiankunking 來源:http://www.php.cn/
許多應用程式中,綁定了許多應用程式中,綁定了一組類型中,綁定了一組類型中,綁定了一組類型中,綁定了(Type)或類型成員(從MemberInfo派生),並將這些物件保存在某種形式的一個集合中。以後,會搜尋這個集合,找出特定的對象,然後呼叫這個對象。這是一個很好的機制,但有個小問題:Type和MemberInfo衍生的物件需要大量的記憶體。如果一個應用程式容納了太多這樣的類,但只是偶爾用一下它們,應用程式的記憶體就會急劇增長,對應用程式的效能產生影響。
在內部,CLR用一種更精簡的形式來表示這種資訊。 CLR之所以為應用程式建立這些對象,只是為了簡化開發人員的工作。 CLR在運作時並不需要這些大物件。如果需要快取大量Type和MemberInfo派生對象,開發人員可以使用運行時句柄(runtime handle)來取代對象,從而減少工作集(佔用的記憶體)。 FCL定義了3個運行時句柄類型(都在System命名空間),RuntimeTypeHandle,RuntimeFieldHandle,RumtimeMethodHandle。三個類型都是值類型,他們只包含了一個字段,也就是一個IntPtr;這樣一來,這些類型的實例就相當省內存。 ItPtr字段是一個句柄,它引用了AppDomain的Loader堆中的一個類型,字段或方法。轉換方法:
Type→RuntimeTypeHandle,透過查詢Type的只讀欄位屬性TypeHandle。
RuntimeTypeHandle→Type,透過呼叫Type的靜態方法GetTypeFromHanlde。
FieldInfo→RuntimeFieldHandle,透過查詢FieldInfo的實例只讀欄位FieldHandle。
RuntimeFieldHandle→FieldInfo,透過呼叫FieldInfo的靜態方法GetFieldFromHandle。
MethodInfo→RuntimeMethodHandle,透過查詢MethodInof的實例只讀欄位MethodHandle。
RuntimeMethodHandle→MethodInfo,透過呼叫MethodInfo的靜態方法GetMethodFromHandle。
下面的範例取得許多的MethodInfo對象,把它們轉換成RuntimeMethodHandle實例,並示範轉換前後的記憶體差異。
private void UseRuntimeHandleToReduceMemory() { Show("Before doing anything");//从MSCorlib.dll中地所有方法构建methodInfos 对象缓存 List<MethodBase> methodInfos = new List<MethodBase>(); foreach (Type t in typeof(object).Assembly.GetExportedTypes()) { if (t.IsGenericType) continue; MethodBase[] mbs = t.GetMethods(c_bf); methodInfos.AddRange(mbs); } //显示当绑定所有方法之后,方法的个数和堆的大小 Console.WriteLine("# of Methods={0:###,###}", methodInfos.Count); Show("After building cache of MethodInfo objects");//为所有MethodInfo对象构建RuntimeMethodHandle缓存 List<RuntimeMethodHandle> methodHandles = new List<RuntimeMethodHandle>(); methodHandles = methodInfos.ConvertAll<RuntimeMethodHandle>(m => m.MethodHandle); Show("Holding MethodInfo and RuntimeMethodHandle"); GC.KeepAlive(methodHandles);//阻止缓存被过早垃圾回收 methodInfos = null;//现在允许缓存垃圾回收 Show("After freeing MethodInfo objects"); methodInfos = methodHandles.ConvertAll<MethodBase>(r => MethodBase.GetMethodFromHandle(r)); Show("Size of heap after re-creating methodinfo objects"); GC.KeepAlive(methodHandles);//阻止缓存被过早垃圾回收 GC.KeepAlive(methodInfos);//阻止缓存被过早垃圾回收 methodInfos = null;//现在允许缓存垃圾回收 methodHandles = null;//现在允许缓存垃圾回收 Show("after freeing MethodInfo and MethodHandle objects"); }
結果如下:
Heap Size = 114,788 - Before doing anything # of Methods=10,003Heap Size = 2,205,652 - After building cache of MethodInfo objects Heap Size = 2,245,744 - Holding MethodInfo and RuntimeMethodHandle Heap Size = 2,171,976 - After freeing MethodInfo objects Heap Size = 2,327,516 - Size of heap after re-creating methodinfo objects Heap Size = 247,028 - after freeing MethodInfo and MethodHandle objects
以上就是C# 使用綁定句柄來減少進程的記憶體耗用的內容,更多相關內容請關注PHP中文網(www.php.cn)!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

Video Face Swap
使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

使用 C# 的 Active Directory 指南。在這裡,我們討論 Active Directory 在 C# 中的介紹和工作原理以及語法和範例。

多線程和異步的區別在於,多線程同時執行多個線程,而異步在不阻塞當前線程的情況下執行操作。多線程用於計算密集型任務,而異步用於用戶交互操作。多線程的優勢是提高計算性能,異步的優勢是不阻塞 UI 線程。選擇多線程還是異步取決於任務性質:計算密集型任務使用多線程,與外部資源交互且需要保持 UI 響應的任務使用異步。

可以採用多種方法修改 XML 格式:使用文本編輯器(如 Notepad )進行手工編輯;使用在線或桌面 XML 格式化工具(如 XMLbeautifier)進行自動格式化;使用 XML 轉換工具(如 XSLT)定義轉換規則;或者使用編程語言(如 Python)進行解析和操作。修改時需謹慎,並備份原始文件。
