Android開発でのパフォーマンス設計のBest Practice

Googleの公式のドキュメントでは、パフォーマンス向上のための基本的な指針が提示されています。GCの方式の違いやプロセッサの違いなどで、一般的なJavaでの開発とはかなり違った形での開発が要求されるので、特にJava屋さんには注意が必要です。

Best Practices - Design for Performance
http://developer.android.com/guide/practices/design/performance.html

Avoid Creating Objects

短命のオブジェクトを作るな!GCでアプリが停止するから。

Mark & Sweepしている間にアプリケーションスレッドが全部とまってしまうので、GC発生させないように、短命のオブジェクトを作らないようにしてGC極力発生しないようにしましょうという話。

Use Native Methods

String.indexOf(), String.lastIndexOf()とかc++で実装されてるnative method使いましょうという話。

Prefer Virtual Over Interface

Map myMap1 = new HashMap();

ではなくて、

HashMap myMap2 = new HashMap();

と書けと。

Java屋さんだと普通は上で書いてしまうので、この辺注意が必要ですね。実装を隠蔽するんじゃなくて、そのまま使えと。上と下で、2倍以上の速度差があるって話なので注意が必要です。

Prefer Static Over Virtual

オブジェクトの変数にアクセスする必要がなければ、staticな関数にしましょうという話。

これは、仮想関数テーブルにアクセスする必要がないので早いと。

Avoid Internal Getters/Setters

外部からのアクセスはgetter, setter経由でしていいが、クラス内部ではgetter, setterつかわないでメンバ変数にダイレクトにアクセスしろと。

androidのFW側のコードは、この辺はメンバ変数は頭にmつけて、ダイレクトにアクセスしてますね。

Cache Field Lookups

これはダメで、

for (int i = 0; i < this.mCount; i++)
      dumpItem(this.mItems[i]);

以下のように記述しましょうと。

  int count = this.mCount;
  Item[] items = this.mItems;
 
  for (int i = 0; i < count; i++)
      dumpItems(items[i]);

for文の2番目のところはローカルアクセス変数のアクセスにしましょうと。
JSとかでも要素のアクセスすると遅いので、上記のような最適化が行われますが、近い話ですね。

Declare Constants Final

定数はfinalで定義。
コンパイラがインライン展開してくれるから早いって話ですね。

Use Enhanced For Loop Syntax With Caution

Avoid Enums

Enumは使うな!

compileタイムチェックが聞くので便利だけど、サイズ大きくなるし、Enumでアクセスするとstatic fieldへのアクセスが発生しちゃうので。

だから、Enum前の時代のように変数をstatic finalで定義してコンパイラにインライン展開させたほうがいいですよねーという話。

Use Package Scope with Inner Classes

private変数定義するのが一般的なお作法だけど、Inner ClassからOuter側のメンバ変数にはダイレクトできたほうが早いので、package scopeつかいましょうと。

前のgetter, setterの話と同じで、ダイレクトアクセスできることがパフォーマンス上重要と。

Avoid Float

embedded processors frequently do not have hardware floating point support, so all operations on "float" and "double" are performed in software.

ので、float, doubleは避けましょうという話。

まとめ

簡単にまとめると、

  • GCは(極力)発生させない
  • コンパイラの気持ちになって考える

ということになります。