修正後のコードは次の通り。
修正したのはクラス名とPoint.AddRefStructのケースでの処理時間が加算ではなく代入になっていた点(104行目の"refStructTicks += sw.ElapsedTicks;")
結果は次の通り。
size: 1000 AddStruct: 104 (1.00) AddRefStruct: 23 (0.22) AddInterface: 148 (1.42) size: 10000 AddStruct: 250 (1.00) AddRefStruct: 220 (0.88) AddInterface: 914 (3.65) size: 100000 AddStruct: 2332 (1.00) AddRefStruct: 2184 (0.94) AddInterface: 7715 (3.31) size: 1000000 AddStruct: 21937 (1.00) AddRefStruct: 21208 (0.97) AddInterface: 73993 (3.37)読み取れること:
- 繰り返し回数が少ない場合はインターフェースを経由しない参照渡しが速い
- ただし繰り返し回数を増やすとインターフェースを経由しない参照渡しと値渡しとの差は数パーセントまで小さくなる
- インターフェースを経由させると経由させない場合と比較して3倍以上遅くなる
この結果からメソッドに構造体を渡す場合は値渡しでいいと思う。ref修飾子を書いて参照渡しにしても数パーセントしか違いがないならわざわざそんなことをする意味はない。どうせほかの部分の処理時間で関係なくなる。
またインターフェース経由で渡した場合は遅いので実行速度のパフォーマンスが気になる個所ではそれは避けるようにしたほうがいい。
最後に、前回の計測と今回の計測では環境が違う。
前回はたぶんWindows 7, Visual Studio 2010、今回はWindows 10, Visual Studio 2015。それに加えてPCも違う。
前回の計測ではインターフェース経由でない値渡しの場合とインターフェース経由の場合での差が1.0倍から1.7倍くらいだったが、今回の計測ではそれが3倍以上になっているのは、Visual Studio(Visual C#)のコード生成処理が更新されていることが原因だと思う。
自分が試したところ
返信削除修正前のコード
size: 1000
AddStruct: 282 (1.00)
AddRefStruct: 16 (0.06)
AddInterface: 219 (0.78)
size: 10000
AddStruct: 1157 (1.00)
AddRefStruct: 166 (0.14)
AddInterface: 1595 (1.38)
size: 100000
AddStruct: 11712 (1.00)
AddRefStruct: 1735 (0.15)
AddInterface: 14980 (1.28)
size: 1000000
AddStruct: 116013 (1.00)
AddRefStruct: 17162 (0.15)
AddInterface: 143832 (1.24)
修正後のコード
size: 1000
AddStruct: 281 (1.00)
AddRefStruct: 229 (0.82)
AddInterface: 265 (0.94)
size: 10000
AddStruct: 1167 (1.00)
AddRefStruct: 1797 (1.54)
AddInterface: 1670 (1.43)
size: 100000
AddStruct: 11826 (1.00)
AddRefStruct: 18000 (1.52)
AddInterface: 14731 (1.25)
size: 1000000
AddStruct: 115404 (1.00)
AddRefStruct: 181291 (1.57)
AddInterface: 142785 (1.24)
となった(同一PC/コンパイル環境にて実施(.NET4))
なおインターフェース呼び出しの場合は、IL的に仮想メソッドを呼び出しを行っているので
遅くなっていると思われる。