C#+WPFチューニング戦記

C#とWPFで高速なコードと最適なシステムを書くためにやってきたいろいろな事を書いてみます。.NET Frameworkのソースコードを読み解きましょう。なお、ここに書かれているのは個人の見解であって何らかの団体や企業の見解を代表するものではありません。

値型に対する拡張メソッドは、値型のサイズを検討してから

PointとSizeとRectとVectorは業務がら大変高頻度で使うのですが、小さい構造体ながら彼らのIsNaNが馬鹿にならないほど圧迫してきます。とはいっても、10分起動して6億回程度・・・・。

double.IsNaNはRect使用時に2~4回程度、ちょっとした矩形の合成でもやはり数回使われています。何が言いたいかといえば一言で遅いのです。ちなみに演算そのものは最小限です。double値のアドレスをlong*にキャストしてlong値を取得し、ビット演算を2回。これ以上短くできようはずもありません。アセンブラ的には最短と言って良いレベルになります。

ただ、このRect群にはNaNは絶対に入っていないという保証がある場合、これらの処理は無駄なのです。そういうわけで、double.IsNaN等判定を全く省く拡張メソッドを作ってみました。

・・・・遅い。

理由はすぐにわかりました。

Rectに拡張メソッドを作ろうとしてみたら、呼び出すごとに第1パラメータとして32バイト(Rectのサイズ)の余計なスタックが生まれて過剰コピーに苦悩することになりました。

ソースを壊さないという前提で、非publicな メソッドは全部 ref で呼び出すという、これまた気持ちの悪いコードと、大量のRectをまとめて一括合成するメソッドなどを生成してしのぐ羽目となりました。

PointやSizeやVectorの場合、拡張メソッドにしても遅くなるという感じはありませんでした。どうも、16バイトあたりを目安として、大量のスタック転送というものを見直すのが良いようです。