ホームページ  >  記事  >  バックエンド開発  >  C# はバインド ハンドルを使用してプロセス メモリの消費を削減します

C# はバインド ハンドルを使用してプロセス メモリの消費を削減します

黄舟
黄舟オリジナル
2017-02-13 11:32:491928ブラウズ


多くのアプリケーションでは、一連の型 (Type) または型メンバー (MemberInfo から派生) がバインドされ、これらのオブジェクトは何らかの形式のコレクションに格納されます。その後、このコレクションで特定のオブジェクトが検索され、呼び出されます。これは優れたメカニズムですが、小さな問題があります。Type および MemberInfo から派生したオブジェクトは大量のメモリを必要とします。アプリケーションにそのようなクラスが多すぎるにもかかわらず、それらをたまにしか使用しない場合、アプリケーションのメモリが急速に増加し、アプリケーションのパフォーマンスに影響を与えます。

内部的には、CLR はこの情報をより合理化された形式で表現します。 CLR は、単に開発者の作業を容易にするために、アプリケーション用にこれらのオブジェクトを作成します。 CLR は実行時にこれらの大きなオブジェクトを必要としません。多数の Type および MemberInfo 派生オブジェクトをキャッシュする必要がある場合、開発者はオブジェクトの代わりにランタイム ハンドルを使用して、ワーキング セット (占有されるメモリ) を減らすことができます。 FCL は、RuntimeTypeHandle、RuntimeFieldHandle、および RumtimeMethodHandle という 3 つのランタイム ハンドル タイプ (すべて System 名前空間内) を定義します。 3 つの型はすべて値型であり、含まれるフィールドは 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 派生オブジェクトをキャッシュする必要がある場合、開発者はオブジェクトの代わりにランタイム ハンドルを使用して、ワーキング セット (占有されるメモリ) を減らすことができます。 FCL は、RuntimeTypeHandle、RuntimeFieldHandle、および RumtimeMethodHandle という 3 つのランタイム ハンドル タイプ (すべて System 名前空間内) を定義します。 3 つの型はすべて値型であり、含まれるフィールドは 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 中国語 Web サイト (www.php.cn) に注目してください。 )!


声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。