cscとmcsの比較

この間の続きで、こんどは同一ソースをcscとmcsでコンパイルしたものを比較してみました。って言ってもループ回すだけの単純なものなので差はつかないと思うんですけど・・・
コンパイルしたアセンブリは以下の通りです。

まずは、pcsc.exeとpmcs.exeをMono上で実行してみました。尚、結果は差が出たところのみ抜粋しています。

> mono pmcs.exe
FixedConst        :00:00:12.0310000
> mono pcsc.exe
FixedConst        :00:00:08.0160000

fixedブロックを使ったケースでmcsが遅いです。

次に.NET1.1上で実行してみます。

> pmcs.exe
FixedConst        :00:00:12.5156250
ArrayLocal        :00:00:06.4218750
> pcsc.exe
FixedConst        :00:00:08.1093750
ArrayLocal        :00:00:08

fixedブロックでmcsが遅いのは相変わらずですが、ローカル変数を使ったケースではmcsが逆転しています。ildasmで逆アセしてみたところ、ArrayLocalについては基本的に同一コードなんですが、分岐命令がmcsではbr(Unconditional branch to label)やblt(Branch to label if less than)を使っているところをcscではbr.s,blt.sとなっているだけです。.sがついているのはshort formと呼ばれるもので、ジャンプ範囲がbyte(-128〜127)で収まる場合に使える命令でして、コードサイズが通常5のところが2で済みます。つまり、cscの方がコンパクトなコードになっているんですが、速度で負けているのです。IL上の話なのでこれがJITされてx86コードに落ちたときに違いがあるのでしょうが、それ以上は私の手に余るので・・・(^^;
もう一つの、FixedConstではcscは配列をbyte&としているところをmcsではbyte*としているのと、先ほどのbr/br.sの違いだけです。br/br.sについてはパフォーマンスロスにならないので、配列の型の違いが影響しているとしか考えられません。ReflectorでC#のソースに戻してみたら、無駄なキャストが行われていたので、その辺が原因ではないかと・・・

と、歯切れの悪い結果に終わりました。(^^;

あと、試しにC#2.0でコンパイルしてみたところC#1.1よりも遅い結果になってびっくり。C#2.0で最適化オプションをつけて漸くC#1.1と同じ速度になったのですが、これは何でだろう・・・
あ、これはあくまでもコンパイラの比較でランタイムの速度は.NET1.1よりも.NET2.0の方が速いです。