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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
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
markdown-poster Introduction
kazamori
0
160
AI駆動開発はどこまで来たのか? ファインディの最新実態調査で読み解く現在地 Devin Con Tokyo
akiratom
1
1k
Android skills に学ぶ
kokiko
0
180
AI for Science時代を切り開く、政府の次世代HPC戦略の展望
gpuunite_official
0
250
わたしが知り合いゼロの勉強会に 行けるようになるまで
r5ni4
2
790
カーネルまで探検して理解するふたつの自動計装
sumiyae
0
320
NANDでも描画したい!
nichica906
3
730
三人寄ればチューリング完全
puhitaku
6
3.2k
LLMアプリ、 雰囲気で運用してませんか? 〜LLMOpsの現在地〜
taka_aki
1
100
パスキーでドライブする アカウント統合(OAuth/OIDC Numa (Immersion) Workshop 2026)
oidfj
PRO
0
280
Kiro5兄弟のいまどきのセキュリティ基礎知識
kentapapa
0
260
形式手法特論:Hyperproperty とモデル検査 #kernelvm / Kernel VM Study Tokyo 19th
ytaka23
0
810
Featured
See All Featured
Collaborative Software Design: How to facilitate domain modelling decisions
baasie
1
290
Navigating Weather and Climate Data
rabernat
0
490
Claude Code どこまでも/ Claude Code Everywhere
nwiizo
67
57k
Ten Tips & Tricks for a 🌱 transition
stuffmc
0
180
Ethics towards AI in product and experience design
skipperchong
2
350
Imperfection Machines: The Place of Print at Facebook
scottboms
270
14k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
480
Tell your own story through comics
letsgokoyo
1
1k
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
The Cost Of JavaScript in 2023
addyosmani
55
10k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Efficient Content Optimization with Google Search Console & Apps Script
katarinadahlin
PRO
1
810
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