web-dev-qa-db-ja.com

「stackalloc」キーワードの実用化

C#でプログラミング中に誰かが実際にstackallocを使用したことがありますか?私はそれが何をするのか知っていますが、それが私のコードに現れるのは偶然だけです。なぜなら、たとえばstaticと入力し始めるとIntellisenseがそれを提案するからです。

stackallocの使用シナリオとは関係ありませんが、実際にはアプリでかなりの量のレガシー相互運用を行っているため、ときどきunsafeコードを使用することができます。それにもかかわらず、私は通常unsafeを完全に回避する方法を見つけます。

そして、.Netの単一スレッドのスタックサイズは〜1Mb(間違っている場合は修正してください)なので、stackallocを使用することからさらに予約されています。

「これが私にとって安全でない状態になり、stackallocを使用するための正確な量のデータと処理です」と言える実用的なケースはありますか?

114
Groo

stackallocを使用する唯一の理由は、パフォーマンス(計算または相互運用性)です。ヒープに割り当てられた配列の代わりにstackallocを使用することにより、GCのプレッシャーが少なくなり(GCの実行が少なくて済みます)、配列を固定する必要がなく、ヒープ配列よりも速く割り当てられます。メソッドの終了時に自動的に解放されます(ヒープに割り当てられた配列は、GCの実行時にのみ解放されます)。また、ネイティブアロケータ(mallocまたは.Netに相当するもの)の代わりにstackallocを使用することにより、スコープ終了時の速度と自動割り当て解除も得られます。

パフォーマンスに関しては、stackallocを使用すると、データの局所性によりCPUでキャッシュヒットする可能性が大幅に増加します。

126
Pop Catalin

Stackallocを使用して、[ほぼ]リアルタイムのDSP作業用のバッファーを割り当てました。これは、パフォーマンスを可能な限り一貫させる必要がある非常に特殊なケースでした。一貫性と全体的なスループットには違いがあることに注意してください。この場合、プログラムのその時点でのガベージコレクションの非決定性だけで、ヒープ割り当てが遅すぎることは心配していませんでした。 99%のケースでは使用しません。

35
Jim Arnold

stackallocは、安全でないコードにのみ関係します。マネージコードの場合、データを割り当てる場所を決定できません。値タイプはデフォルトでスタックに割り当てられます(参照タイプの一部である場合を除き、その場合はヒープに割り当てられます)。参照タイプはヒープに割り当てられます。

プレーンVanilla .NETアプリケーションのデフォルトのスタックサイズは1 MBですが、これはPEヘッダーで変更できます。スレッドを明示的に開始する場合は、コンストラクターのオーバーロードを介して異なるサイズを設定することもできます。 ASP.NETアプリケーションの場合、デフォルトのスタックサイズは256Kのみです。これは、2つの環境を切り替える場合に留意する必要のあることです。

23
Brian Rasmussen

スパンのStackalloc初期化。 C#の以前のバージョンでは、stackallocの結果はポインターローカル変数にのみ保存できました。 C#7.2の時点で、stackallocは式の一部として使用でき、スパンをターゲットにできるようになりました。これは、unsafeキーワードを使用せずに実行できます。したがって、書く代わりに

Span<byte> bytes;
unsafe
{
  byte* tmp = stackalloc byte[length];
  bytes = new Span<byte>(tmp, length);
}

簡単に書くことができます:

Span<byte> bytes = stackalloc byte[length];

これは、操作を実行するためにスクラッチスペースが必要であるが、比較的小さなサイズのヒープメモリの割り当てを避けたい場合にも非常に便利です

Span<byte> bytes = length <= 128 ? stackalloc byte[length] : new byte[length];
... // Code that operates on the Span<byte>

出典:C#-スパンのすべて:新しい.NETメインステイの探索

9
anth