ホームページ  >  記事  >  バックエンド開発  >  .NET のパフォーマンス向上の詳細な説明

.NET のパフォーマンス向上の詳細な説明

黄舟
黄舟オリジナル
2017-03-09 15:41:551499ブラウズ

.NET 4.6 では、パフォーマンスの向上に関連するいくつかの CLR 機能が導入されています。これらの機能の一部は自動的に有効になりますが、SIMD や非同期ローカル ストレージなどの一部の機能では、アプリケーションの記述方法を変更する必要があります。

SIMD

Mono チームは、単一命令ストリーム、複数データ ストリーム機能である SIMD のサポートを常に誇りに思っています。 SIMD は、最大 8 つの値に対して同じ演算を同時に実行できる CPU 命令セットです。 .NET CLR バージョン 4.6 のリリースにより、Windows 開発者はついにこの機能を使用できるようになりました。

SIMD の効果を実際に観察するには、この例を参照してください。 3 番目の配列を取得するには、c[i] = a[i] + b[i] の形式で 2 つの配列を追加する必要があるとします。 SIMD を使用すると、次の方法でコードを書くことができます:

for (int i = 0; i < size; i += Vector.Count)
 {
     Vectorv = new Vector(A,i) + new Vector(B,i);
     v.CopyTo(C,i);
 }

このループが Vectorbd43222e33876353aff11e13a7dc75f6.Count の値によってどのように増加するかに注目してください。この値は、CPU タイプに応じて 4 または 8 になります。 .NET JIT コンパイラは、CPU に応じて値 4 または 8 の配列をバッチ追加するための対応するコードを生成します。

この方法は少し面倒に見えるため、Microsoft は次のような一連の補助クラスも提供しています:

  • Matrix3x2 構造

  • Matrix4x4 構造

  • 平面構造

  • クォータニオン構造

  • ベクタークラス

  • Vector(T) 構造

  • Vector2 構造

  • Vector3 構造

  • Vector4 構造

アセンブリのアンインストール

残念ながら、ほとんどの開発者はこのことを知りません。.NET は同じアセンブリを 2 回ロードすることがよくあります。これが発生する条件は、.NET が最初にアセンブリの IL バージョンをロードし、続いて同じアセンブリの NGEN バージョン (つまり、プリコンパイルされたバージョン) をロードすることです。このアプローチは、特に Visual Studio などの大規模な 32 ビット アプリケーションの場合、物理メモリを大幅に浪費します。

.NET 4.6 では、CLR がアセンブリの NGEN バージョンを読み込むと、対応する IL バージョンが占有しているメモリが自動的にクリアされます。

ガベージコレクション

前に、.NET 4.0 で導入されたガベージ コレクション待機モードについて説明しました。この方法は、GC を一定期間完全に停止させるよりもはるかに信頼性が高くなりますが、多くの GC シナリオではまだ不十分です。

.NET 4.6 では、より洗練された方法でガベージ コレクターを一時的に停止できるようになり、新しい TryStartNoGCRegion メソッドを使用して、小さいオブジェクトと大きいオブジェクトのヒープに必要なメモリ量を指定できます。

メモリが不足している場合、ランタイムは false を返すか、GC クリーニングによって十分なメモリが確保されるまで実行を停止します。 TryStartNoGCRegion にフラグを渡すことで、この動作を制御できます。GC フリー領域に正常に入った場合 (プロセスが終了するまで GC は許可されません)、プロセスの最後に EndNoGCRegion メソッドを呼び出す必要があります。

公式ドキュメントには、このメソッドがスレッドセーフであるかどうかは記載されていませんが、GC の動作原理を考慮すると、2 つのプロセスが同時に GC 状態を変更しようとすることは避ける必要があります。

GC のもう 1 つの改良点は、ピン留めされたオブジェクト (つまり、一度割り当てられると移動できないオブジェクト) を処理する方法です。この点についてはドキュメントでは多少曖昧に説明されていますが、オブジェクトの位置を修正すると、通常、隣接するオブジェクトの位置も修正されます。リッチ・ランダーは記事の中で次のように書いています:

GC はピン留めされたオブジェクトをより最適化された方法で処理するため、GC はピン留めされたオブジェクトの周囲のメモリをより効果的に圧縮できます。多数のピンを使用する大規模なアプリケーションの場合、この変更によりアプリケーションのパフォーマンスが大幅に向上します。

GC は、以前の世代のメモリの使用方法においても優れたインテリジェンスを示しています:

第 1 世代のオブジェクトを第 2 世代のオブジェクトに昇格させる方法も改善され、メモリをより効率的に使用できるようになりました。世代に新しいメモリ領域を割り当てる前に、GC はまず利用可能な領域を使用しようとします。同時に、利用可能なスペース領域を使用してオブジェクトを作成するときに新しいアルゴリズムが使用されるため、新しく割り当てられたスペースのサイズが以前よりもオブジェクトのサイズに近づきます。

非同期ローカルストレージ

最後の改善はパフォーマンスに直接関係しませんが、効果的に活用することで最適化の結果を達成できます。非同期 API が普及する前の時代、開発者はスレッド ローカル ストレージ (TLS) を利用して情報をキャッシュすることができました。 TLS は、特定のスレッドに対してグローバル オブジェクトのように機能します。つまり、コンテキスト オブジェクトを明示的に渡さなくても、コンテキスト情報に直接アクセスしてキャッシュすることができます。

非同期/待機モードでは、スレッドのローカル ストレージは役に立たなくなります。 await が呼び出されるたびに、別のスレッドにジャンプすることができるためです。また、この状況を回避できたとしても、他のコードがスレッドにジャンプして TLS の情報を妨害する可能性があります。

新しいバージョンの .NET では、この問題を解決するために、非同期ローカル ストレージ (ALS) メカニズムが導入されています。ALS は意味的にはスレッド ローカル ストレージと同等ですが、await の呼び出しで対応するジャンプを行うことができます。この関数は AsyncLocal ジェネリック クラスを通じて実装され、内部で CallContext オブジェクトを呼び出してデータを保存します。


以上が.NET のパフォーマンス向上の詳細な説明の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

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