こんにちは、きねぶちです。
スマホアプリは応答性が最重要です。スマホというのは生活のあらゆる局面で使われるので、PCユーザ以上にアプリの応答時間にシビアです。
ですから、初級者以上のすべてのエンジニアにとってAndroidアプリの高速化というのは最重要技法だと思います。これまでなかなかまとまった情報がありませんでしたが、インプレスから「Androidアプリ高速化プログラミング」という本が出版されました。
今や「0.1秒」ルールの時代!
昔のWebは「3秒ルール」
昔、Webがまだ牧歌的だった時代、「Webの3秒ルール」などと言われていました。Webサイトのページ表示に3秒以上かかるとユーザはページを離脱してしまうので、3秒以内に表示すべし、というものです。(クライアントがこの呪文を唱えるたびに、エンジニアの会社泊が1泊ずつ増えていくという強烈なブリザード系呪文でもありました)
一桁速くなる
しかし、スマホの時代では、文字通り桁が変わりました。今や、スマホでは「0.1秒ルール」が重要であると思います。
タッチしてからアプリが反応するまで「0.1秒」以上かかると、ユーザはイライラしはじめるというものです(ものです、っていうか僕が勝手に作ったルールですが(笑)。
ユーザというのは(自分も含め)冷酷なもので、ちょっとでもイライラすると即座にアンインストールしてしまいます。ですから、今の時代高速化技法というのは、一般に認識されているよりもはるかに重要です。
Android高速化技法を網羅する優れた解説書
「Androidアプリ高速化プログラミング」(インプレスジャパン刊)は、Androidアプリの最適化、高速化の技法を詳細に解説した非常に実践的で興味深い書籍です。これまではAndroid開発そのものが珍しかったので「つくってみようAndroidアプリ」的な書籍が多かったのですが、Android開発文化が熟してきて、こうした実践的な解説書が出版されるようになり、面白くなってきました。
快適アプリの鉄則
キビキビ動く快適なアプリを作るには、3つの鉄則があります。- スレッドを活用する
- 描画を最適化する
- GCの実行を抑える
スレッドの活用
マルチスレッドプログラミング、イヤですよねー。しかし、上で述べた「0.1秒ルール」を実現するためにはスレッド処理は必要不可欠です。
「0.1秒ルール」を実現するには、次のような処理が必要になります。
ユーザ操作に対してまず0.1秒以内にいったん応答を返しておき、時間のかかる処理はバックグラウンドで並行して実行して、処理が完了した時にもう一度フィードバックする。
こう考えると、Androidアプリの開発には、マルチスレッドプログラミングの正確な理解と適切な使用が必要不可欠です。
Androidでは、AsyncTaskといって、Java標準のFutureTaskを拡張した便利クラスがあり、このクラスを使うことで目からウロコが落ちるくらい簡単にマルチスレッド処理が記述できます。
しかし、いくら便利クラスを使っても、ぞんざいに書くと簡単にクラッシュしたりメモリリークを起こしますから、スレッド処理はやはり慎重なコーディングが必要です。
本書の第5章で「マルチスレッド」について詳しく書かれています。
Javaのスレッドモデルから解きおこし、AsyncTaskの使い方や別スレッドからUIを操作するといった基本的な技法、謎のクラス「Handler」とイベントループの仕組みも丁寧に解説されています。
特に重要なのがアクティビティのライフサイクルとスレッドの関係を解説した節です。
AsyncTaskでマルチスレッドにしたからといってライフサイクルが自動的にマルチスレッド化されるわけではないこと、マルチスレッド化した際のアクティビティ間/スレッド間での安全なデータの受け渡し方法など、実際にマルチスレッドプログラミングを始めると必ず落ちる落とし穴について、きちんと解説されています。
描画を最適化する
XMLレイアウトは非常に便利な機能ですが、油断しているとどんどん描画が重くなり、なんとなく動作がもっさりしたイケてないアプリができあがってしまいます。深く深く深くネストしてしまったレイアウトXMLファイルを見て、見るからに遅そうだなあ、整理したいなあ、けどどうやって手を付けたらいいか分からないと思う人は多いと思います。
第8章でレイアウトの最適化技法が詳しく解説されていて、レイアウトファイルを整理するときにどこから手を付ければいいか、整理の視点を与えてくれます。
実際の使用時までインフレートを遅らせることで、アプリの起動処理を高速化する遅延初期化技法も解説しています。
Android3.0から導入された高速3DフレームワークRenderScriptの解説に1章割かれています。
GCの実行を抑える
がんばって他を最適化しても、JavaにはGCという悪魔のルールがあります。DalvikVMのGCはよくできていると思います。GCの精度は高く、かなり敏感にガベージコレクトが行なわれ、不要なメモリがどんどん増えていくということはほとんどありません。
また、GCが走ったからといって、大昔のJavaのように、あからさまに実行が止まったりもしません。
しかし、むろんGCの実行コストはゼロではありません。GCの実行回数を減らすことは「0.1秒ルール」を実現するために非常に重要です。GCが頻繁に走ると、もっさり、ではなく「カクカク」したアプリができあがります。これはなんとしても避けなければなりません。
そのためにはメモリの最適化が必要です。
本書の4章「メモリを効率的に使用する」でメモリの最適化技法が解説されています。
メモリ最適化で理解しておかなければならないのは、
1.キャッシュAPI
2.強い参照と弱い参照の違い
の2つです。僕も「強い参照と弱い参照の違い」は理解が曖昧な部分だったのですが、本章の解説を読んでよく分かりました。
「強い参照」と「弱い参照」の違いは、オブジェクトがどの時点で誰に所有され、いつ解放された(GCの対象となる)と認識されるのかにかかわるもので、GCがいつどのように走るかに影響を与えます。
ですから、その区別をしっかり理解しておかないと、不必要にオブジェクトをつかんでしまい、「いらなくなったのにGCされた」とか「まだ使ってるのにGCされてクラッシュ」などの事態が発生します。
「AndroidってJavaだからメモリ管理いらないんでしょ」と思ってると痛い目見ます。
AndroidはJavaじゃありません。ていうか、Javaですけど、それはシステム記述言語がJavaなだけであって、JavaVMとは違うのです(ややこしい言い方ですが)。
ですから、その辺いい加減にコーディングしていると、あなたが思っているよりはるかに簡単にクラッシュします。メモリ管理技法を身につけることは非常に重要です。
その他の重要技法
NDK
NDKが2章と3章で解説されていますが、日本語でこれほどまとまったNDKの解説はそうそうないので、非常に貴重です。ネイティブプログラミングは、最後の最後にどうにもならなくて、清水の舞台から飛び降りるようなつもりで採用する特殊技法のような扱いでした。
しかし、非常に丁寧かつディープに解説されている本書のNDKの章を読めば、特殊技法でもなんでもなく、いくつかの定型的なルールにのっとればいいだけの単なるお作法プログラミングであることが分かります。
NDKを理解して気軽に利用できるようになっておくと、開発の幅が大きく広がることは間違いありません。
プロファイル
アプリが遅い!となったとき、やみくもにあちこちをいじり回しても効率がよくありません。
高速化の基本は、まず現状を把握してボトルネックを突き止めるところから始まります。
「推測するな計測せよ」という有名な言葉がありますが、どこでどれだけの時間がかかっているかを測ることが重要です。
Android SDKについてくるプロファイルツールTraceViewの使い方に第6章が割り当てられています。
いい本です
マルチスレッド、描画、NDKは、誰もが「なんとなく苦手だなー」と思う3大ジャンルでしょう。そして「でも理解しておかなくちゃなあ」とも思う3大ジャンルでもあるはずです。この重要な3つの技法が実に分かりやすく解説されている本書は、間違いなく良書です。
いきなりアセンブラのソースが出てきたりしてたまげる箇所もありますが、全体としては、いたずらに解説を複雑化させることなく、必要十分で実践的に分かりやすく解説されています。
ディープなところはディープに、歴史的経緯などのように、知らなくてもいい背景知識は適度に省略されていて、知りたい情報はほぼ完璧に網羅されているといってよく、しかも情報がとてもうまく整理された優れた解説書です。
アマゾンで立ち読みできますので、よろしければこちらからどうぞ。
0 コメント:
コメントを投稿