星1つのレビューでは42%のユーザーが安定性やバグについて言及している
星5つのレビューでは73%のユーザーがスピード、デザイン、使いやすさについて言及している
ANR 率やクラッシュ率が上がると、ユーザーがアプリで費やす時間が有意に減る
Android vitals とは、Android デバイスの安定性とパフォーマンスを向上するための Google が主導する取り組み
もっとも重要なパフォーマンスメトリクスであるバッテリー、安定性、レンダリングの情報を開発者にわかりやすく提供する
データ提供を opt in している1億以上のユーザーからの情報
昨年 Android vitals をリリースしてから 10,000 以上の開発者がコンソールからパフォーマンスを理解した
昨年に比べ、スピード、デザイン、使いやすさについて言及している星5つのレビューは 4% 増え、安定性やバグに言及している星1つのレビューは 18% 減り、リソースの使用について言及している星1つのレビューは 21% 減った
Starbucks アプリは ANR rate が 70% 減り、Crash rate が 85% 減った
ANR は 3rd party のライブラリで起こっていたため、自分たちの観測に引っかかっていなかった
Android vitals はプラットフォームレベルのツールなので、Starbucks の 3rd party crash SDK では検出できていなかったクラッシュを見つけることができた
なぜならそのクラッシュは 3rd party crash SDK が開始される前に起こっていたため
Kiloo の Subway Surfers というゲームでは ANR を 95% 減らすことができた
昨年 Android vitals を公開したとき、バッテリー、安定性、レンダリングの3つの項目があった
新しくアプリのスタートアップ時間(App startup time)と権限(Permissions)が追加された
Vitals
- バッテリー(Battery)
- 安定性(Stability)
- レンダリング(Rendering)
- New: アプリのスタートアップ時間(App startup time)
- コールド スタートアップ時間が長い(Slow cold start)
- ウォーム スタートアップ時間が長い(Slow warm start)
- ホット スタートアップ時間が長い(Slow hot start)
- New: 権限(Permissions)
- 権限リクエストの拒否率(Permission request denials)
バッテリー(Battery)
- 停止した wake lock
- 過度の wakeup
- 過度のバックグラウンドでの Wi-Fi スキャン
- 過度のバックグラウンドでのネットワーク使用
安定性(Stability)
- ANR 発生率
- クラッシュ発生率
レンダリング(Rendering)
- フリーズした UI フレーム
- 遅いレンダリング
New: アプリのスタートアップ時間(App startup time)
- コールド スタートアップ時間が長い : 5秒以上
- ウォーム スタートアップ時間が長い : 2秒以上
- ホット スタートアップ時間が長い : 1.5秒以上
New Metric: コールド スタートアップ時間が長い
- 5秒以上かかると遅いと判断
- コールドスタート :
- Activity が起動してから running になるまで
- Activity launched → onCreate() → onStart() → onResume() → Activity running
- アプリがしばらく使われておらず、アプリがメモリ上にいない状態からスタート
New Metric: ウォーム スタートアップ時間が長い
- 2秒以上かかると遅いと判断
- ウォームスタート :
- Activity が起動してから running になるまで
- Activity launched → onCreate() → onStart() → onResume() → Activity running
- アプリが最近使われており、アプリがメモリ上にいる状態からスタート(アプリはkillされていない)
New Metric: ホット スタートアップ時間が長い
- 1.5秒以上かかると遅いと判断
- ホットスタート :
- onRestart() から running になるまで
- onRestart() → onStart() → onResume() → Activity running
- アプリと Activity がメモリ上にいる状態からスタート
New: 権限(Permissions)
アプリのコアバリューに必要な権限だけをリクエストし、必要に応じて権限リクエストの正当な理由をランタイム時に提供する- 権限リクエストの拒否率
権限の詳細ビューでは権限をグループに分けて表示しているので、どの権限がユーザーにとって納得感があり、どの権限が不必要だと思われているかがわかる
Android Vitals の詳細の内訳
- 一般的な内訳
- APK versionごと
- デバイスごと
- Android versionごと
- Wake locks, wakeups
- tag ごと
- ANR率
- Activity 名ごと
- ANR type ごと
- Clusters
- クラッシュ率
- Clusters
カテゴリーベンチマーク
自分のアプリの vital が特定のカテゴリーの中でどのくらい良いかを見ることができるvital の各 metric でパーセンタイル 25, 50, 75 の値を見ることができる
概要画面で全ての vital がリストされ、直近の30日とその前の30日の値、ベンチマークの値を見ることができる
概要画面の主な指標(Core Vitals)には Google Play でのアプリの表示やランキングに影響するパフォーマンス指標が表示される
主な指標が下位25%より悪くなると Bad behavior として表示される
異常検知(Anomaly Detection)
新リリースやリグレッションの結果値に急変があるとアラートを出す- ANRやクラッシュ率の大きな変化
- 主な指標(Core Vitals)の大きな変化
主な指標(Core Vitals)を改善するには
ANRの原因- Network / Disk operations
- Long calculations
- InterProcess Communication (IPC)
- Locks and Synchronization
- Slow BroadcastReceiver handling
Network / Disk operations
例: SharedPreferences インスタンスを生成する時点で Disk 処理が行われる
override fun onCreate(state: Bundle?) {
// この時点で Disk 処理が行われる
prefs = PreferenceManager.getDefaultSharedPreferences(this)
}
どのメソッドが Network 処理や Disk 処理をするのか理解するのは難しいので StrictMode を利用する
class MyApplication : Application() {
override fun onCreate() {
super.onCreate()
if (BuildConfig.DEBUG) {
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyDeath()
.build())
}
}
}
Long calculations
例: 数独ゲームの盤面生成に時間がかかる
Android Profiler で CPU の使用をチェックする
ちなみに Android Studio 3.2 Canary ではスタートアップ時間をプロファイルできるようになっている
StrictMode にはこのメソッドを呼ぶと遅くなるということを指定できる
class GenerateBoardSource() {
fun generateBoard(seed: Long) : SudokuGame {
StrictMode.noteSlowCall("Generating Sudoku board")
return SudokuSolver.generate()
}
}
StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder()
...
.detectCustomSlowCalls()
...
.build())
InterProcess Communication (IPC)
- 他のアプリを呼び出す場合、基本こちらに制御権がない
- 呼び出し先が Network 処理や Disk 処理をするかもしれないので別スレッドで呼び出す
Locks and Synchronization
- これはとても難しい問題
- deadlock になったり main thread をブロックするかもしれない
- デバッグが難しい
- Android Vitals が提供する trace file の情報がデバッグに役立つかもしれない
Slow BroadcastReceiver handling
- Android Manifest に BroadcastReceiver を登録した場合、onReceive メソッドは main thread で呼び出される
- 実行に時間がかかる処理を onReceive() でやるべきではない
- 10秒以内に処理を終えないと ANR になる
- Notification に表示する画像を Disk から読み出すなどちょっとした Disk 処理が必要な場合は onReceive() で goAsync() を呼び、別のスレッドを立ち上げ、終わったら PendingResult.finish() を呼ぶ
- https://developer.android.com/guide/components/broadcasts#effects-process-state
- あまり長いと結局システムに kill されるので、長い処理が必要なら JobScheduler や WorkManager を使う
クラッシュ対策
- クラッシュの対応として Activity のライフサイクルでむやみに null チェックや例外の握りつぶしをするべきではない
- 車輪の再発明をしない : 問題を解決する利用できるライブラリを使う
- Lifecycle handling (LiveData, ViewModel)
- Database object mapping (Room)
- Data paging (Paging)
- *NEW* Fragment transitions, up/back, deep link handling (Navigation)
- *New* Job scheduling (WorkManager)
- 3rd party の優れたライブラリもたくさんある
- Kotlin を使う : でも全てのクラッシュを防げる銀の弾丸ではないよ!
- private / hidden API を使わない
バッテリー対策
停止した wake lockwake lock が取得されたが適切に release されなかった
- wake lock を使わない
- 画面をつけっぱなしにしたいなら Activity の Window に FLAG_KEEP_SCREEN_ON を指定する
- 自分で Service を管理せず job を schedule する
- AlarmManager で BroadcastReceiver を起こすようにすると onReceive() の間 AlarmManager は wake lock を hold してしまう
- wake lock を使わなければ permission も必要なくなる
- どうしても wake lock を使わないといけないなら、常に PARTIAL_WAKE_LOCK を使うこと
- wakeLock.acquire() にタイムアウトをセットすること
- static な descriptive tag を渡すこと(Android Vitals でのデバッグがしやすくなる)
- try { ... } finally { wakeLock.release() } すること
過度の wakeup
- もっとも大きい原因は AlarmManager の *_WAKEUP アラーム
- 可能ならなくす(Remove)
- 頻度を減らす(Reduce)
- FCM, WorkManager, JobScheduler, SyncManager などに置き換える(Replace)
- Android Studio 3.2 Canary に追加された Energy Profiler で wake lock に関する問題をデバッグできる
関連
- Autonomous and customized pre-launch testing in the Google Play Console (Google I/O '18)
- Don't let your app drain your users' battery (Google I/O '18)
- g.co/AndroidStudio
- g.co/Firebase
- Firebase Crashlytics
- Firebase Performance Monitoring
- Improve app performance and stability with Firebase (Google I/O '18)
- g.co/androidvitals
0 件のコメント:
コメントを投稿