2020年8月4日火曜日

Build app fast on Android Studio 4.+(Android 11 Meetup登壇)

Android 11 Meetups にて、Android Studio 4.0以降に追加された Build Analyzer、CPU Profiler、Database Inspectorなどの新機能を使って効率的に高性能なアプリを開発する方法について発表しました。

https://developersonair.withgoogle.com/events/a11meetups-jp/watch?talk=android-dev-tool

Android 11 Meetups は Android 11 Beta のリリースを機に、アプリ開発の最新技術情報をお届けすべく、Google と GDG (Google Developer Groups)が共催するオンラインセミナーシリーズです。

以下に発表のスクリプトを公開します。


Build app fast on Android Studio 4.+

Android Studio Releases

はじめに今公開されているAndroid Studioのバージョンについて紹介します。

Android OSのアップデートとともに開発環境Android Studioも便利な機能が追加され、更新されています。

Android StudioのリリーストラックはStable、Beta、Canaryがあります。
正式リリース版であるStableは4.0、次のリリース候補のBetaは4.1、開発中版のCanaryは4.2まで公開されています。
BetaやCanaryはまだ大きな変更が入る可能性があるので、実際の開発に使う場合は自己責任ですが、Android studio最新の機能を試すことができます。
更新も頻繁に行われており、Gradle Pluginのアップデートも含めるとそれぞれのバージョンで月に数回アップデートが配信されています。

Gradleの更新などが入るとコードやビルドスクリプトの修正が必要になる場合があります。
差分が大きくなると修正が難しくなるため、できる限りこまめにバージョンアップすることをおすすめします。

Pick up New Features

Android Studio4.0以降で追加、更新された主要な機能としては、ビルドに関する機能、UIの構築をサポートする機能、作ったアプリを分析して改善につなげる機能があります。
本セッションでは特にアプリの開発速度とパフォーマンス向上を支援する機能をピックアップして紹介します。

Android Studio 4.0で大きく改善したアプリの開発速度向上のための機能であるBuild Analyzer、アプリのパフォーマンス解析と改善のための機能であるCPU Profilerについてと、4.1 Preview で導入された Database Inspector の紹介をしていきます。
4.2 Canary の注目機能であるJetpack ComposeのサポートやUI開発系のツールについては、この後のセッションで詳しく解説しますのでここでは触れません。

Build Analyzer

早速機能の紹介に移ります。
はじめにアプリの開発速度を向上するための機能として、Build Analyzerを紹介します。

Build Analyzer

Build AnalyzerはAndroid studio上でのビルドの速度をPlugin、taskごとに解析しビルドを最適化する助けになるツールです。
Android Studio4.0でAndroid Gradle plugin 4.0.0以降から使えます。

Open Build Analyzer window

Build AnalyzerのウィンドウはAndroid Studioの下部のBuildウィンドウの中のBuild Analyzerタブで開きます。
Buildウィンドウがメイン画面で開いていない場合は画面上部のViewセクションからTool Windowsの中のBuildを選択してください。
Build AnalyzerはAndroid Studio上で行われるすべてのビルドを解析しています。
RunボタンやBuildコマンドを実行したらその結果が表示されているので開いてみましょう。

Tabs

Build AnalyzerにはOverview、Tasks、Warningsのタブがあります。
Overviewではビルドが実行された時間や合計時間などが表示されます。

Tasks

Tasksを開いてみてみます。
ウィンドウの左側のツリーには、ビルド時間に直接影響を与えるタスクが表示されます。
pluginごとまたはtaskごとの表示を切り替えられます。
右側のペインではビルド時間へのインパクトの視覚的な表示と、タスクの詳細が表示されます。

Which tasks determine build duration

一番ビルド時間に影響を与えているタスクの詳細に注目してみましょう。

Which tasks determine build duration

この解析結果を見てみると、processDebugResources という、デバッグ build type でのリソースの処理に時間がかかっていそうです。
これを改善するには、不要なリソースをビルド対象外としたり、画像リソースを軽量化するなどが考えられます。

不要なリソースをビルド対象外とする場合、特定のロケールの言語リソースのみをビルドに含めたり、画面サイズに応じたリソースを開発中はビルド処理の対象から外すようにflavorで指定すると良いかもしれません。
Resourceに画像が多く含まれるのであればWebPなどで画像を最適化するのも良いかもしれません。
Android Developersサイトのビルド速度を最適化する記事をみると多くのヒントが提供されているので、ボトルネックが解消できるか試してみるのがよいでしょう。

Warning tab

[Warnings] タブではビルド時間に悪い影響があると考えられる部分への警告が出ます。

この例では古いプラグインによって依存関係の解決が重複している可能性があると出ています。
古いプラグインでは最新のGradleで改善されているビルド最適化の機能を利用できないためビルドが遅くなります。
Warningに従ってプラグインをアップデートしましょう。

Build duration

Build Analyzerでの注意点は、ビルド時間自体はCacheの状態や変更の内容によって大きく変わることです。
これはAndroid Studio4.2上で同じプロジェクトで小さな変更をおこないビルドしたときの記録です。
初回のビルドでは542秒かかっているのに対して2回目はなんと15秒、3回目は50秒と大きく変動しています。

Build duration

Build Analyzerによるビルド速度の最適化は、一回一回のビルドを細かく解析していくというよりも、プラグインを足したときやビルドが遅いときにチェックし、継続的に対処していくのがよさそうです。

CPU Profiler

次にアプリのパフォーマンス解析と改善のための機能として、Android ProfilerのCPU profilerの更新を紹介します。

CPU Profiler

CPU Profilerではアプリの CPU 使用量やスレッド アクティビティをリアルタイムで確認したり、記録されたメソッド トレース、関数トレース、システム トレースの詳細を調べたりできます。

Android Studio4.0ではCPU ProfilerのUIがアップグレードされて、より分析しやすくなりました。

アプリのCPU使用率を最適化するとアプリの動作が高速でスムーズになります。

またCPUの使用率は端末の電池の使用量と密に関係しており、CPU使用率を最適化すると電池消費が減るなどのメリットもあります。

Open CPU Profiler

CPU Profilerを使う流れをみていきます。

Android Studio画面上部の[View] > [Tool Windows] > [Profiler] 、または画面下部の [Profiler] でプロファイルウィンドウを開きます。

ProfilerからCPUのタイムラインをクリックするとCPU Profilerが開きます。

CPU Profiler(動画)

動画でみてみます。

Android Profilerウィンドウの左側のSESSIONSで実行中の解析したいアプリを選択すると、
そのアプリの CPU 使用率やメモリ使用率がグラフがリアルタイムに表示されます。
解析結果が右から左へ流れていきます。
上部の赤い表示がユーザーのインタラクション、その下の明るい緑のラインが実行されているActivityです。
CPUのグラフをクリックすると、CPUの使用率をより詳細に解析するためのCPU Profilerが開きます。

Record methods

CPUの使用状況をより詳細に解析するためにはメソッドの呼び出しを記録する必要があります。

画面上部または記録が選択されていない場合はウィンドウ中央部からプロファイリングモードを選択します。
モードにはSample Java Methods、Trace Java Methods、Sample C/C++Functions、Trace System Calls、または自分でカスタムするモードがあります。

一番シンプルにアプリのJavaベースのメソッド呼び出しを記録するSample Java Methodsを使ってCPU使用量を最適化する流れを見ていきます。

Sample Java MethodsはアプリのJavaペースのメソッド呼び出しのコールスタックを頻繁に取得しトレースデータを作成します。
Sample Java Methodsはアプリの実行速度を落とすことなく記録ができますが、サンプリングが間に合わない短いライフサイクルのメソッド呼び出しを取り落とすことがあります。

Trace Java MethodsはSampleと同じくJavaのメソッド呼び出しを記録するプロファイルで、インストルメント化という手法を使う事によってライフサイクルの短いメソッドも記録できますが、
アプリの実行速度が落ち本来のパフォーマンスが出なかったり、トレースの上限に達して記録ができなくなる場合もあります。

Javaのメソッドを記録する場合ははじめにSample Java Methodsで解析し、より正確な解析が必要な場合にTrace Java Methodsを使うとよさそうです。

Record methods

ここではRecyclerViewのスクロール時に動作がカクつく原因をメソッド呼び出しを記録して探る例を想定します。

アプリを実行している状態でCPU Profilerのウィンドウ上部かタイムラインの下部にあるメニューでプロファイルを選び、Recordボタンをおして記録を開始します。
パフォーマンスを計測したい操作をアプリで行い、終わったら記録をStopします。
自動的に記録された結果が読み込まれ、表示が変わります。
Recording の開始と終了のタイミングを解析したい箇所に合わせて記録するのがコツです。

Record Methods

Sample Java Methodsプロファイリングを記録するとこのように表示されます。
左側のペインには、横軸を経過時間としてCPUの使用率、ユーザーのインタラクション、Activityのライフサイクル、スレッドのコールチャートが表示されます。

CPU使用率のラインで選択したタイムボックスのコールチャートを下部に詳しく表示します。
黄色、緑、青で視覚的に表示されているのが記録されたコールチャートです。

左右に長いほどCPUの使用時間を占めています。
実行時間を占めていたり、メソッドコールスタックが縦に多く重なっている部分がパフォーマンス低下を引き起こしている原因だとあたりをつけてより詳細に追っていきます。

Select a method call

ひとつのメソッドコールを選択すると右側のペインにコールチャートの詳細が表示されます。
Summary、Flame Chart、Top Down、Bottom Upの4つのタブがあります。

はじめにFlame Chartを選択してみます。

Flame Chart

Flame Chartは同一のコールスタックを集約し反転したチャートです。
同じコールスタック内で同じ経路で呼び出されたメソッドコールをまとめ、積み上げて表示します。

左右に長いほどCPU時間を占めています。
繰り返し呼び出されているメソッドも集約されているので、合計時間としてCPUを占めているメソッドコールを見つけられます。

時間がかかっているものを絞り込んでいくために、このグラフのスタックの上の方でこのように左右に広がっている部分に注目します。
発見したメソッドコールをTop Down、Bottom Upでより詳細に見ていきます。

Top Down

Top Downチャートでは呼び出し元からのコールスタックをツリーで表示していて、時間のかかる処理を絞り込むのに最適です。
それぞれのメソッドコールにかかる時間をself、子の呼び出しでかかる時間をchildrenから詳細に読み取れるので時間のかかるメソッドコールを特定するときに使います。

Flame Chartでみつけたメソッドコールが実際にどれくらいの時間がかかっているのかをこのViewで詳細に確認します。

Bottom Up

Bottom Upは呼び出し一覧から呼び出し元をノードで表現するグラフです。
記録されたすべてのメソッドコールが一覧で並んでいるので時間のかかっているメソッドコールを見つけるのに適しています。

これらのチャートの考え方の詳細はAndroid DevelopersサイトのCPU のホットスポットを特定する、の記事を参照してください。

Flame ChartやTop DownやBottom Upであたりをつけたら該当するメソッドのコードの問題を修正し、再度CPU Profilerで修正されたか確認しましょう。

このようにSample Java MethodsプロファイルでCPU使用量に問題があるメソッド呼び出しを見つけることができますが、
必ずパフォーマンス低下の原因を見つけられるとは限りません。
メソッドの記録が適切ではないと感じたらTrace Java Methodsプロファイルで記録をしてみたり、Memory Profilerでメモリ使用に問題がないか確認してみたりしましょう。

ここまでがRecord MethodsのSample Java MethodsでCPUのパフォーマンスを確認する流れです。

ここでもうひとつUIレンダリングパフォーマンスの最適化に使える、Record MethodsのTrace System Callsプロファイルを紹介します。

Record methods (Trace System Calls)

Trace system calls では、メインスレッドでの画面の描画にかかる時間を解析でき、UI ジャンクや低フレームレートの原因を探る手がかりとなります。

Renderingウィンドウではメインスレッドと RenderThread で各フレームをレンダリングする際にかかる時間を調べて、UI ジャンクと低フレームレートの原因となるボトルネックを調査できます。

Framesで赤く表示される16msを超えるフレームを探しましょう。
対応するThreadを選択するとJava Sample Methodsのときと同様にトレース情報の詳細から原因を探ることができます。

Improve App Performance

ここまでCPU Profilerの新しいUI、機能を使ってボトルネックを検証する方法を紹介しました。
CPU Profilerはタブからすぐに起動できるので、開発中にアプリの動作が重いなと感じたらすぐにひらいて改善に繋げられるとよいでしょう。

Android Profilersには今回紹介したCPU Profiler以外にもパフォーマンスを改善する機能として、メモリ使用量をモニタするMemory Profiler、ネットワーク通信の状況を監視するNetwork Prodiler、電池の消費量への影響が見れるEnergy Profilerがあります。
アプリの動作が重いときの原因がCPUだけに起因することは稀です。
Android Profilersの機能を横断的に使って効果的にアプリのパフォーマンスを上げていきましょう。

Database Inspector

最後におすすめするAndroid Studioの新しい機能は4.1で追加されるDatabase Inspectorです。

Database Inspector

今までAndroidアプリの書き込むSQLite databaseのデータはデータベースファイルをデバイスから引き出しツールで詳細を見るか、ADB shell経由で確認するしかありませんでした。
Database Inspectorは実行されてるアプリのDatabaseをAndroid studioから変更して反映させ動作を確認できます。

開発中のアプリにAndroid Studioからクエリを実行してデータの検証ができたり、値の更新をしてデータをモック化したりと開発に役立てることができます。

新しいDatabase InspectorはAndroid studioからDatabase Inspectorを開けばそれだけでAndroid Studio上でリアルタイムにDatabaseの状態を確認できます。
特に難しい設定は不要です。Roomを使っていても、SQLiteDatabase APIを直接利用していてもDatabase Inspectorは使えます。

Database Inspectorウィンドウが開いていない場合は[View]>[Tool Windows]>[Database Inspector]から開きます。

Run query from the code

Android JetpackのRoomを使っている場合はクエリの検証を簡単にできます。
Android StudioでRoomの@Queryアノテーションの左側をみてください。
テーブルと虫眼鏡のマークが表示されます。

Run query

これをクリックして実行すると実行結果がタブが表示されます。
ここからクエリを修正し実行もできるため、クエリの調整が素早く簡単にできます。

Update database

Database Inspector でデータベースに変更を加えると、アプリの UI にもその変更が反映できます。
テーブルのデータを直接編集してRefresh Tableをクリックするとデータベースの値が書き換えられます。

データベースの値を表示するアプリであれば画面を更新するとデータの書き換えが確認できます。
サンプルのようにLiveDataを使っている場合アプリ上での操作なしにデータベースの更新が即座に画面に反映できます。

Database Inspector

このようにアプリのデータベース周りの実装の確認を簡単にできるようになりました。
なお現在のところクエリの実行と値の書き換えはできますが、データのinsertはサポートしていないようです。

また、この機能は他のデータ書き換えに比べてとても簡単で反映も速いため、
例えばAPIレスポンスのモックなど、データを変更してのテストも簡単にできるかもしれません。

終わりに

Android Studio4.0以降の更新でパフォーマンスの高いアプリを高速で開発するのをサポートするおすすめの新機能を紹介してきました。

AndroidはOSも開発環境も高い頻度で便利で高性能な機能を発表しています。

開発効率化のためにもできるだけ最新のアップデートに追従するようにしましょう。

Gradleやpluginのバージョンによってはアプリの修正が必要になりますが、差分が大きくなるとより修正が困難になるのでこまめにメンテナンスをしましょう。

最後にもう一度ですが、Beta、CanaryバージョンはあくまでPreviewなので開発に悪影響を及ぼす場合もあるので、製品アプリで試す場合は慎重に行いましょう。
自分の場合は複数バージョンの開発環境をキープしておいて試すなどしています。
しかし新しいバージョンごとに便利な機能が追加され、ビルドも高速化しているので、できるならばぜひ新しいバージョンを試して、なにかあったらフィードバックを送り、パフォーマンスが高いアプリを効率的に素早く開発していきましょう。

ご視聴ありがとうございました。