Garminウォッチフェイスの作成:パフォーマンス4

パフォーマンス向上のための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にコンパイラー?による最適化がない前提で書いている。最適化ができるかどうかについては判断ができなかった。

将来的に最適化ができるようになれば、上記のような実装テクニックは必要なくなるかもしれない。

コメント

タイトルとURLをコピーしました