Track memory allocations(日本語超訳)

前回の「Avoiding Memory Leak*1」に続いて、Androidのメモリ関連で興味深い記事だったので、また30分ほどでぐゎっと超訳。誤訳御免、ツッコミ歓迎。JavaGCは切っても切れないけど、パフォーマンスに影響しないようにアプリケーションを書くには重要なポイントだと思うし、Androidのチームがメモリ管理に気を配っていることが読める。

Romain Guy著


最初のAndroid携帯(T-Mo G1とADP1)のハードウェア性能はびっくりするくらいだけど、でも効率的なモバイルアプリケーションを書くのは一筋縄ではいかないことが多い。Androidのアプリケーションは、Dalvik仮想マシンのガベージコレクタ(GC)によってメモリが自動的に管理されることに依存している。メモリアロケーションを意識していないと、時々GCはパフォーマンス上の問題を引き起こす。


Viewのレイアウトや描画をするメソッドとか、ゲームのロジックのように、パフォーマンスに影響のある一連のコードでは、どんなメモリアロケーションもしかるべき対価を払わなければならない。あまりに多くのアロケーションを行うと、GCが起動され、アプリケーションを停止し、メモリの一部を開放する。多くの場合、GCは十分に速く、気づかれることはないだろう。しかし、もしGCがアイテムリストをスクロールしている間に起きたり、ゲームで敵を倒そうとしているときに起きたりすると、アプリケーションのパフォーマンスや反応速度が、急に落ちたように思うだろう。GCが100msec、200msecを必要とすることは珍しいことではない。比較のために例をあげると、滑らかなアニメーションは16msecから33msecごとにフレームを描画しなければならない。もしアニメーションが10フレームも突然に中断されたら、アプリケーションのユーザがすぐに気付くことは目に見えている。


大半のケースでは、数多くの小さくて短命なオブジェクトが原因でGCが起動される。世代別GC*2のような場合には、このようなオブジェクトの回収を最適化し、頻繁にGCが起動されることを防ぐことができる。AndroidGCは、残念ながらそのような最適化を行うことができず、パフォーマンスに影響の多い一連のコードの中で、短命なオブジェクトを作ると、そのままアプリケーションの性能にとって影響が多くなってしまう。


頻繁にGCが発生することを防ぐために、「Allocation Tracker」というとても便利なツールがAndroid SDKに含まれている。このツールはDDMSの一部で、デバッグのために使ってみたことがあるに違いない。Allocation Trackerを起動するには、最初にまずスタンドアローン版のDDMSを起動する。SDKのtoolsディレクトリに入っている。EclipseプラグインのDDMSには、Allocation Trackerの機能はまだ提供されていない。


DDMSが起動したら、アプリケーションのプロセスを選択し、[Application Tracker]タブをクリックする。新しいビューで、[Start Tracking]をクリックして、解析したい一連のコードが実行されるようにアプリケーションを操作する。準備ができたら、[Get Allocations]をクリックする。アロケートされたオブジェクトの一覧が、最初のタブに表示される。ある行をクリックすると、アロケーションが発生するに至ったスタックトレースが、2つ目のテーブルに表示される。オブジェクトのタイプが分かるだけではなく、どのスレッドで、どのクラスで、どのファイルと行で、アロケートされたかが分かる。次のスクリーンショットはListViewをスクロールしている最中にShelevesによってアロケーションされていることを示す。


パフォーマンスに影響の大きいコード部分からすべてのメモリアロケーションを取り除くことは、必要のないことだし、不可能なことも多いが、「Allocation Tracker」はコードの中で重要な問題を発見するのに役立つ。たとえば、自分のアプリケーションの中でよくやってしまう間違いは、描画のたびに新しいPaintオブジェクトを生成してしまうことだ。インスタンスのフィールドにPaintを移動させるだけで、パフォーマンスは大きく改善できる。Androidソースコードを見て、パフォーマンス改善のために、クリティカルな部分でのアロケーションを減らすために、いかに努力をしたか見てほしい。またAndroidにはオブジェクトを再利用するためのAPIがあることも発見するだろう。


注: この記事は最初に個人的なブログに投稿されたものです。