Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
JankStats LibraryでJankを検出しよう / Detecting Jank w...
Search
KeitaTakahashi
July 11, 2023
Technology
1.9k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
JankStats LibraryでJankを検出しよう / Detecting Jank with JankStats Library
KeitaTakahashi
July 11, 2023
More Decks by KeitaTakahashi
See All by KeitaTakahashi
誰と働くか / Who I work with
tkhskt
1
190
ZOZOTOWN AndroidへのJetpack Composeの導入 / Introducing Jetpack Compose for ZOZOTOWN Android
tkhskt
1
12k
Other Decks in Technology
See All in Technology
Foxgloveについて 実際にExtensionを開発して公開するまでの話 / About Foxglove: The Story of Developing and Releasing an Extension
ry0_ka
0
210
あなたの『Site』はどこですか? — xREという考え方
miyamu
0
1.2k
cccccc
moznion
0
1.9k
“それは自分の仕事じゃない"を越えて行け
yuukiyo
0
190
Claude Codeとハーネスについて考えてみる
oikon48
18
9.4k
kintone の AI コワーカーを、 Anthropic にエージェントを"ホストさせて"作った話 #devkinmeetup
sugimomoto
0
100
プロダクトだけじゃない、社内プロセスにおける自動化・省力化ノススメ
kakehashi
PRO
1
3.7k
SRE依存からの脱却 運用を開 発チームへ移す、 フルサイ クル開 発体制の実践
joooee0000
0
2.7k
しぶいSRE: サーバから見えない障害にどう向き合うか。ラストワンマイルのデバッグ実践 / Shibui SRE
kanny
13
6.1k
なぜ私たちのSREプラクティスはなかなか機能しないのか 〜システムより先に組織を見る〜 / Why our SRE practices aren't really working
vtryo
3
3.7k
大量データに対しても、生成AIを用いてリーズナブルにデータ加工をしたい!Databricksのai_queryについて調べてみた
kamoshika
1
120
Genie Ontologyは銀の弾丸かを考える / Is Genie Ontology a Silver Bullet?
nttcom
0
250
Featured
See All Featured
Sam Torres - BigQuery for SEOs
techseoconnect
PRO
0
300
Measuring & Analyzing Core Web Vitals
bluesmoon
9
880
The Spectacular Lies of Maps
axbom
PRO
1
850
The Art of Programming - Codeland 2020
erikaheidi
57
14k
4 Signs Your Business is Dying
shpigford
187
22k
A Guide to Academic Writing Using Generative AI - A Workshop
ks91
PRO
1
350
How to optimise 3,500 product descriptions for ecommerce in one day using ChatGPT
katarinadahlin
PRO
1
3.7k
Applied NLP in the Age of Generative AI
inesmontani
PRO
4
2.4k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
123
22k
Pawsitive SEO: Lessons from My Dog (and Many Mistakes) on Thriving as a Consultant in the Age of AI
davidcarrasco
0
190
The agentic SEO stack - context over prompts
schlessera
0
840
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
500
Transcript
JankStats LibraryでJankを 検出しよう 2023/07/11 ZOZO Tech Meetup - iOS/Android 株式会社ZOZO
ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android2ブロック Androidテックリード 高橋啓太 Copyright © ZOZO, Inc. 1
© ZOZO, Inc. 2 株式会社ZOZO ZOZOTOWN開発本部 ZOZOTOWNアプリ部 Android2ブ ロック Androidテックリード
高橋 啓太 2020年新卒入社
© ZOZO, Inc. 話すこと 3 • JankStats Libraryの基本的な情報 • Jankとは
• Jank検出ツール • JankStats Libraryの基本的な使用方法
© ZOZO, Inc. JankStats Libraryの基本的な情報 4 • アプリのレンダリングパフォーマンスに関する情報を取得することができる ◦ 後述する「Jank」を検出可能
• FrameMetrics APIやOnPreDrawListenerの上に構築されている • 2023/07/11時点ではApril 5, 2023リリースの1.0.0-alpha04が最新 • android/nowinandroidにも入っている Metrics | Jetpack | Android Developers: https://developer.android.com/jetpack/androidx/releases/metrics android/nowinandroid | GitHub: https://github.com/android/nowinandroid
© ZOZO, Inc. 5 Jankとは
© ZOZO, Inc. Jankとは 6 遅いレンダリング | App quality |
Android Developers: https://developer.android.com/topic/performance/vitals/render?hl=ja • ユーザーがスムーズにアプリを操作するためには、各デバイスで決められたリフ レッシュレートを達成できるようフレーム生成時間を維持することが必要 ◦ 一般的には60fpsを達成することが必要 • なんらかの理由でフレームがスキップされ、アプリの動作がスムーズでなくなるこ とを「Jank(ジャンク)」と呼ぶ
© ZOZO, Inc. Jankとは - ANR等との関係性 7 ジャンクのトラッキング | App
quality | Android Developers: https://developer.android.com/topic/performance/vitals/tracking_jank?hl=ja 遅いフレーム フリーズしたフレーム ANR 表示に要する時間 16ms~700ms 700ms~5s 5sより長い ユーザーが知覚できる現象の例 リストのスクロールがカクつく 画面遷移時がスムーズではない 画面をタップしても5秒以上反応がな い
© ZOZO, Inc. Jankとは - ANR等との関係性 8 → これらは全てJankに分類される 遅いフレーム
フリーズしたフレーム ANR 表示に要する時間 16ms~700ms 700ms~5s 5sより長い ユーザーが知覚できる現象の例 リストのスクロールがカクつく 画面遷移時がスムーズではない 画面をタップしても5秒以上反応がな い ジャンクのトラッキング | App quality | Android Developers: https://developer.android.com/topic/performance/vitals/tracking_jank?hl=ja
© ZOZO, Inc. Jankとは - ANR等との関係性 9 → これらは全てJankに分類される →
Jankの検出・修正は、快適な操作感を維持するために重要 遅いフレーム フリーズしたフレーム ANR 表示に要する時間 16ms~700ms 700ms~5s 5sより長い ユーザーが知覚できる現象の例 リストのスクロールがカクつく 画面遷移時がスムーズではない 画面をタップしても5秒以上反応がな い ジャンクのトラッキング | App quality | Android Developers: https://developer.android.com/topic/performance/vitals/tracking_jank?hl=ja
© ZOZO, Inc. 10 Jank検出ツール
© ZOZO, Inc. Perfetto 11 • ADBを介して、Android端末からフレームの情報を含むパフォーマンス情報を取得 するツール • 取得したパフォーマンス情報はPerfetto
UIで可視化して分析可能 • ZOZOTOWNではスクロール時のJankを分析する際に使用した Perfetto: https://perfetto.dev/ perfetto | Android Developers: https://developer.android.com/studio/command-line/perfetto?hl=ja Perfettoを用いたAndroidアプリのボトルネックの特定とその改善 | ZOZO TECH BLOG: https://techblog.zozo.com/entry/android-performance-improvement-with-perfetto
© ZOZO, Inc. AndroidStudio Profiler 12 • Chipmunk以降のAndroid StudioではProfilerでJankを検出可能 ◦
Android12以降の端末が必要 Android Developers Japan Blog: Android Studio の CPU profiler で UI のジャンクを検出する https://android-developers-jp.googleblog.com/2022/07/spot-your-ui-jank-using-cpu-profiler-in-android-studio.html
© ZOZO, Inc. JankStats Library 13 • androidx.metrics.performance • 下記の機能を提供する
◦ Jankの識別 ▪ Jankの発生タイミングに関する情報を取得できる ◦ Jankが発生した時点でのアプリの状態取得 ▪ Jankが発生した際にユーザーがどのような操作をしていたかを確認できる ◦ 結果のレポート ▪ フレームに関する情報(完了にかかった時間など)を取得できる
© ZOZO, Inc. JankStats Libraryの何が良いのか? 14 • 開発環境でのJank検出はPerfettoやAndroid StudioのProfilerで十分可能 •
しかし、本番環境(ユーザーの手元)で実際に発生しているJankを検出することは できない • JankStats Libraryをプロダクトに導入し、データを収集することで、本番環境で発 生しているJankの原因が分析可能になる ◦ 取得したデータの保存やデータを送信する仕組みは提供されていない ※「保存とアップロードに関する詳細情報は、JankStats API アルファ版リリースでは提供されません」 とあるので将来的になんらかのサポートが追加される可能性はある https://developer.android.com/topic/performance/jankstats?hl=ja
© ZOZO, Inc. 15 JankStats Libraryの基本的な使用方法
© ZOZO, Inc. 16 JankStats Libraryの基本的な使用方法 ※alpha版のため今後APIが変更される場合があります
© ZOZO, Inc. 導入 17 implementation "androidx.metrics:metrics-performance:1.0.0-alpha04" 何はともあれimplementation
© ZOZO, Inc. class MainActivity : ComponentActivity() { private lateinit
var jankStats: JankStats override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ... } jankStats = JankStats.createAndTrack(window) { frameData -> if (frameData.isJank) { // Jankと判定されたフレームかどうか Log.v("Jank detected!", frameData.toString()) } } } } 基本的な使用方法 - 初期化 18 JankStats.createAndTrackでJankStatsのインスタンスを生成
© ZOZO, Inc. class MainActivity : ComponentActivity() { private lateinit
var jankStats: JankStats override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ... } jankStats = JankStats.createAndTrack(window) { frameData -> if (frameData.isJank) { // Jankと判定されたフレームかどうか Log.v("Jank detected!", frameData.toString()) } } } } 基本的な使用方法 - 初期化 JankStats.createAndTrackでJankStatsのインスタンスを生成 19 JankStatsのインスタンス生成時にdecorViewが生成されていない場合、 IllegalStateExceptionが発生するので注意
© ZOZO, Inc. 基本的な使用方法 - 初期化 20 class MainActivity
: ComponentActivity() { private lateinit var jankStats: JankStats override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContent { ... } jankStats = JankStats.createAndTrack(window) { frameData -> if (frameData.isJank) { // Jankと判定されたフレームかどうか Log.v("Jank detected!", frameData.toString()) } } } } JankStats.createAndTrackの第二引数には、フレーム情報を受け取るコールバック (JankStats.OnFrameListener)を渡す
© ZOZO, Inc. 21 isTrackingEnabledでフレーム情報収集の有効/無効を切り替える(デフォルト値はtrue) class MainActivity : ComponentActivity() {
... override fun onResume() { super.onResume() ... jankStats.isTrackingEnabled = true } override fun onPause() { super.onPause() jankStats.isTrackingEnabled = false } } 基本的な使用方法 - 初期化
© ZOZO, Inc. 基本的な使用方法 - FrameData 22 FrameData(フレームの情報)がLogcatに出力される
© ZOZO, Inc. 基本的な使用方法 - FrameData 23 • frameStartNanos ◦
フレームの開始時刻(ns) • frameDurationUiNanos ◦ フレームの長さ(ns) • isJank ◦ ジャンクかどうかを示すフラグ • states ◦ アプリの状態 (StateInfo) JankStats ライブラリ | App quality | Android Developers: https://developer.android.com/topic/performance/jankstats?hl=ja#reporting
© ZOZO, Inc. 基本的な使用方法 - FrameData 24 • frameStartNanos ◦
フレームの開始時刻(ns) • frameDurationUiNanos ◦ フレームの長さ(ns) • isJank ◦ ジャンクかどうかを示すフラグ • states ◦ アプリの状態 (StateInfo) JankStats ライブラリ | App quality | Android Developers: https://developer.android.com/topic/performance/jankstats?hl=ja#reporting
© ZOZO, Inc. 基本的な使用方法 - FrameData 25
© ZOZO, Inc. 基本的な使用方法 - FrameData 26 空だが...?
© ZOZO, Inc. @Composable fun rememberMetricsStateHolder(): PerformanceMetricsState.Holder { val view
= LocalView.current return remember(view) { PerformanceMetricsState.getHolderForHierarchy(view) } } 基本的な使用方法 - PerformanceMetricsState 27 PerformanceMetricsState.Holderを使用する
© ZOZO, Inc. 基本的な使用方法 - PerformanceMetricsState 28 @Composable fun JankyScreen()
{ val holder = rememberMetricsStateHolder() val key = "画面名" LaunchedEffect(holder) { // 状態を設定 holder.state?.putState(key, "JankyScreen") } JankyLazyColumn() // Jankが発生するComposable } PerformanceMetricsState#putStateにkey-value形式で状態をアプリの設定する
© ZOZO, Inc. 基本的な使用方法 - PerformanceMetricsState 29
© ZOZO, Inc. 基本的な使用方法 - PerformanceMetricsState 30 フレーム情報と アプリの状態が対応する🎉
© ZOZO, Inc. 基本的な使用方法 - PerformanceMetricsState 31 @Composable fun JankyScreen()
{ ... Column { Button(onClick = { // 無効になった状態を削除 holder.state?.removeState(key) }) { Text(text = "状態削除") } JankyLazyColumn() } }
© ZOZO, Inc. 基本的な使用方法 - PerformanceMetricsState 32 ボタンを押す前 ボタンを押した後 状態の削除も明示的に行う必要がある
© ZOZO, Inc. 基本的な使用方法 - nowinandroidの場合 33 nowinandroidではJankStatsを使用したJank検出用のComposableを作成し、 画面遷移時とスクロール時にputState/removeStateを実行している
© ZOZO, Inc. 基本的な使用方法 - nowinandroidの場合 34 nowinandroid | NiaAppState.kt:
https://github.com/android/nowinandroid/blob/main/app/src/main/java/com/google/samples/apps/nowinandroid/ui/NiaAppState.kt @Composable private fun NavigationTrackingSideEffect(navController: NavHostController) { TrackDisposableJank(navController) { metricsHolder -> val listener = NavController.OnDestinationChangedListener { _, destination, _ -> metricsHolder.state?.putState("Navigation", destination.route.toString()) } navController.addOnDestinationChangedListener(listener) onDispose { navController.removeOnDestinationChangedListener(listener) } } }
© ZOZO, Inc. 基本的な使用方法 - nowinandroidの場合 35 nowinandroid | JankStatsExtensions.kt:
https://github.com/android/nowinandroid/blob/4d65946f95f55505a21a1651c2fd5587cd5bb533/core/ui/src/main/java/com/google/samples/apps/nowinandroid/core/ui/JankStatsExtensions.kt @Composable fun TrackScrollJank(scrollableState: ScrollableState, stateName: String) { TrackJank(scrollableState) { metricsHolder -> snapshotFlow { scrollableState.isScrollInProgress }.collect { isScrollInProgress -> metricsHolder.state?.apply { if (isScrollInProgress) { putState(stateName, "Scrolling=true") } else { removeState(stateName) } } } } }
© ZOZO, Inc. JankStats Libraryの使用方法まとめ 36 • フレーム情報の収集はコールバックを登録するだけなのでお手軽 • フレームの情報とアプリの状態を紐づけるには
PerformanceMetricsState#putStateを使用する • 無効になったアプリの状態はremoveStateで削除する • 状態管理にはDisposableEffectやLifecycleObserverを活用するのが良さそう ※ putSingleFrameStateという1フレーム分の状態を登録し、自動で削除するAPIもあります(使い所が難しい) ※
© ZOZO, Inc. 37 まとめと感想
© ZOZO, Inc. まとめと感想 38 • Jankとはフレームがスキップされ、アプリがスムーズでなくなることを指す • JankStats Libraryは本番環境で使用することで価値を発揮する
◦ ユーザーの手元で発生しているJankが検出可能になる ◦ Jankの分析に有用なデータを収集するためには、アプリのどのような情報をフ レームの情報に乗せるかが重要になりそう
None