C# 使用綁定控制代碼來減少進程的記憶體耗用

來源:互聯網
上載者:User


許多應用程式中,綁定了一群組類型(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 objectsHeap Size =   2,245,744 - Holding MethodInfo and RuntimeMethodHandleHeap Size =   2,171,976 - After freeing MethodInfo objectsHeap Size =   2,327,516 - Size of heap after re-creating methodinfo objectsHeap 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 objectsHeap Size =   2,245,744 - Holding MethodInfo and RuntimeMethodHandleHeap Size =   2,171,976 - After freeing MethodInfo objectsHeap Size =   2,327,516 - Size of heap after re-creating methodinfo objectsHeap Size =     247,028 - after freeing MethodInfo and MethodHandle objects

以上就是C# 使用綁定控制代碼來減少進程的記憶體耗用的內容,更多相關內容請關注topic.alibabacloud.com(www.php.cn)!

  • 相關文章

    聯繫我們

    該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

    如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.