ボクシングとアンボクシングは同じパフォーマンスヒットをもたらしますか?または、開梱はより高速です、としましょう?
(はいの場合、主な理由を簡単に説明できますか。)
ありがとう
それは、「開箱」の意味に部分的に依存します。ILの用語では、開開は実際にはC#の場合よりもわずかに少なくなります。C#では、「ボックス化解除」には常に値をどこかにコピーすることが含まれますが、ILでは、ボックスのタイプをチェックし、その方法で値を使用可能にすることだけを意味します。
ただし、パフォーマンス特性は異なります。ボクシングでは新しいオブジェクトを割り当てる必要がありますが、型チェックは必要ありません。
ILレベルでのアンボックス化は、実際には、アンボックス化しようとしているオブジェクトが実際に同じタイプ(または互換性のあるもの)のボックス化された値であることを確認するだけで済みます。次に、C#バージョンのunboxingに値のコピー操作を追加する必要があります。
特に、事前に割り当てるコストだけでなく、対応するガベージコレクションが後でヒットするため、タイプチェックよりも長期的には割り当てのコストが高くなると思います。
いつものように、実際のコードのコンテキストで操作のパフォーマンスコストを評価する必要があります。ジェネリックスを使用してコレクションなどで回避できる最新の.NETアプリケーションでは、ボクシングとアンボクシングのコストが大きくなるとは思いません。
非常に一般的に言えば、ガベージコレクション環境でのボクシングとアンボクシングのパフォーマンスを決定するいくつかの基本的な要因があります。
x64マシンで64ビット整数(long
C#など)について話していると仮定します。さらに、これがトレースガベージコレクションを使用してスタックベースの仮想マシンの内部で行われると仮定します。
まず、ある場所から別の場所に任意の量のメモリを移動するコストがあります。ランタイムは、ボックス化された整数の実際の値をスタックにコピーする必要があります。これにより、ランタイムで何か便利なことができるようになります。同様に、逆の場合は、値をスタックからヒープ(参照型が格納されている場所)にコピーする必要があります。これは、ハードウェアのサブシステムの多くに影響を与えるかなり複雑な操作です。私たちに関する限り、この要素は固定費であると見なすことができ、両方の操作で同じです。
次に、ボクシングの場合、参照型をヒープに割り当てる必要があります。これにより、値が保持されます。これには、予備のメモリの検索、メモリへの適切なオブジェクトヘッダーの書き込み、整数自体の値など、かなりの量のハウスキーピングが含まれます。
第3に、開封の場合、ランタイムは開開操作が実際に合法であり、正しい結果を生成するかどうかを判断するために型チェックを実行する必要があります。場合によっては、ボックス化されていないオブジェクトのタイプを静的に推測できる場合がありますが、これは、実行している操作に直接関連するのではなく、コンパイラーの最適化(またはタイプシステム機能)です。
第4に、ボックス化された整数の隠れた長期的なコストは、他の参照型と同様に、ガベージコレクションに参加する必要があることです。これは、それへの参照を記録する必要があるかもしれないことを意味します、それは活気を決定するために追跡されなければならず、潜在的に別の世代にコピーする必要があります。もちろん、これはすべての参照型に当てはまりますが、このレベルのパフォーマンスについて考えているかどうかを検討する要素です。
要約すると、コストは、コンパイラ、ランタイム、そしてもちろん実行しているハードウェアのバージョン固有の動作の数によって異なります。したがって、簡単な答えを出すのは簡単ではありません。
私の知る限り、開箱はボクシングよりもはるかに安いです。このことを考慮:
Int32 v1 = 5;
v1
スタックに割り当てられます。
Object r = v1; // boxing
コンパイラはの値を取り、v1
それに基づいてオブジェクトを作成します。これには時間がかかります(いくつかの理由により)。
ただし、このコードを実行すると、次のようになります。
Int32 v2 = r; //unboxing
何が起こるかというと、そのコンパイラは、それ自体でボックス化された値へのポインタを取得し、r
それをにコピーしv2
ます。