私は宿題をして、forループの内側または外側に変数を宣言するかどうかにかかわらず、パフォーマンスに違いがないことを繰り返し確信しています。実際には同じMSILにコンパイルされます。それにもかかわらず、私はそれにもかかわらず、ループ内で変数宣言を移動すると、実際にはかなりの一貫性のあるパフォーマンスが得られることが分かりました。forループ内で宣言された変数は、ループのパフォーマンスに影響しますか?
私はこの効果を測定するための小さなコンソールテストクラスを作成しました。私は静的double[]
配列の項目をに初期化し、2つのメソッドがループ操作を実行し、結果を静的double[]
配列バッファに書き出します。元々、私の方法は、私が違いに気づいたもの、すなわち複素数の大きさの計算でした。 の項目をの長さ1000000の配列で100回実行すると、変数(の変数)がループ内にあるものの実行時間が一貫して低くなります。たとえば、32,83±0.64 ms v 43 、Intel Core 2 Duo @ 2.66 GHzの高齢者構成では24±0.45 msです。私はそれらを異なる順序で実行しようとしましたが、結果には影響しませんでした。
static void Square1()
{
double x;
for (int i = 0; i < buffer.Length; i++) {
x = items[i];
buffer[i] = x * x;
}
}
static void Square2()
{
for (int i = 0; i < buffer.Length; i++) {
double x;
x = items[i];
buffer[i] = x * x;
}
}
を、結果は他の方法を出てきましたループの外側がより好ましいように見えた:Square1()
の7.07±0.43ミリ秒Square2()
の12.07±0.51ミリ秒。
私はILDASMに精通していないですが、私は2つのメソッドを解体している、との唯一の違いは、ローカル変数の初期化のようだ:Square1()
V
.locals init ([0] int32 i,
[1] float64 x,
[2] bool CS$4$0000)
で
.locals init ([0] float64 x,
[1] int32 i,
[2] bool CS$4$0000)
Square2()
にあります。それに応じて、stloc.1
が1つで、それはstloc.0
であり、その逆である。より複雑な大きさの計算MSILコードでは、コードサイズが異なっていて、内部宣言コードにstloc.0
があった外部宣言コードでstloc.s i
が見えました。
これはどのようにすることができますか?私は何かを見落としているのですか、それとも本当の効果ですか?そうであれば、長いループのパフォーマンスに大きな違いをもたらす可能性があるので、議論に値すると思う。
あなたのご意見は大変ありがとうございます。
編集:私が見落としたことの1つは、投稿する前に複数のコンピュータでテストすることでした。私は今i5でそれを実行しており、の結果は2つの方法でほぼ同じです。このような誤解を招くような観測結果を投稿したことをお詫び申し上げます。
良い調査、あなたは必ずupvoteを獲得してください。 – NicoRiff
@NicoRiff:確かに、よく書かれた質問です。 (悲しいことに、私は答えは自明だと思うが) – Bathsheba
これで@JonSkeet答えを待つことができない – NicoRiff