パフォーマンス向上のためのTips。
パフォーマンスの計測方法についてはGarminウォッチフェイスの作成:パフォーマンスを参照。
その後、本当に上記の計測が正しいのか、フォーラムのほうも確認してみた。
フォーラムではSystem.getTimer()
を使うとの記載があったのだが、実際にシミュレーターで試してみても、処理時間が0msとなってしまい、正しいのか、正しくないのかが判断できなかった。
パフォーマンス向上のための手法
演算回数を減らす
同じ演算を2回以上行う場合、一度変数に演算を代入し、それを利用するのがいい。
パフォーマンスを見たところ、2回までは、変数に代入したものを利用することでトントン、3回以上同じ計算をしていたら、変数に代入したほうがパフォーマンスが向上した結果となった。
普通のパターン
まずは、Garminウォッチフェイスの作成:パフォーマンス3でも使用していたのだが次のようなコーディング。
for (var i = 1; i < 180; i++) {
var now = [center[0] + radius * Math.cos(baseAngle * i), center[1] - radius * Math.sin(baseAngle * i)];
dc.drawLine(prev[0], prev[1], now[0], now[1]);
prev = now;
}
sin/cosに与える角度を、それぞれの関数呼び出し時に毎回行っている。
ありがちなコードなのだが、このような場合、一度変数に代入してからsin/cosに渡したほうがいい。
for (var i = 1; i < 180; i++) {
var angle = baseAngle * i;
var now = [center[0] + radius * Math.cos(angle), center[1] - radius * Math.sin(angle)];
dc.drawLine(prev[0], prev[1], now[0], now[1]);
prev = now;
}
for文内の判断に使用しているパターン
同様にやりがちなのが、for文の比較部分に関して。
この部分に、演算を行うような実装を行うと、パフォーマンスがダウンする。
a = 5;
b = 4;
for (var i = 1; i < a * b; i++) {
System.println(i);
}
これだと、i < a * b
の部分で、a * b
の演算が毎回入るので、パフォーマンスダウンになる。
for文の前でa * b
を変数に代入し、それとの比較にするといい。
度⇔ラジアン変換
関数の中には、度で指定したり、ラジアンで指定したりと、なかなか一貫していない。
次のように実施するのがいいと思われる。
var toRad = Math.PI / 180.0;
ラジアン = 度 * toRad;
度 = ラジアン / toRad;
toRadに度⇔ラジアン変換用の定数を用意し、それを使い計算する方法。
Mathに変換用の関数があったが、上記の実装の方が10ns位早かった。
描画処理
テキストの描画
テキストの描画はフォントサイズが大きいほど時間がかかった。
処理時間は一緒だが、グラフィック時間に差が出ていた。
円弧の描画
これは、Garminウォッチフェイスの作成:パフォーマンス3で示したように、drawArcではなく、drawLineで線分に分解して描画したほうが全体の処理時間が早くなった。
最後に
ここにあげたパフォーマンス向上手段は、Monkey Cにコンパイラー?による最適化がない前提で書いている。最適化ができるかどうかについては判断ができなかった。
将来的に最適化ができるようになれば、上記のような実装テクニックは必要なくなるかもしれない。
コメント