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
レンダリングしていますを改善する
Search
Naoki Ishii
September 28, 2018
Programming
650
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
レンダリングしていますを改善する
Naoki Ishii
September 28, 2018
More Decks by Naoki Ishii
See All by Naoki Ishii
Walking with Awareness API
iiinaiii
1
510
Other Decks in Programming
See All in Programming
初めての模倣学習とVLA
natsutan
0
190
バグを直したら useEffect が消えた
colorful12
3
690
実装をデザインガイドラインに追従させるための取り組み / 260731-dip-mosh-design-system
dachi023
0
7.6k
go-spidermonkeyでAIエージェントのCode Modeを実装する
syumai
1
700
tsc.rip を支える技術 / Kyoto.なんか #8
susisu
0
120
今さら聞けない .NET CLI
htkym
0
210
React本体のコードリーディング
high_g_engineer
1
150
使いながら育てる Claude Code — 開発フローの1コマンド化 × 繰り返し指摘の自動仕組み化
shiki_kakaku
0
1.9k
170k Jobs a Day on GKE: Scaling Mercari's CI Platform - and What's Next for AI-Native Development
junyaokabe
0
120
源内ハンズオン概要編
hideg
0
210
What's New in Android 2026
veronikapj
0
270
KotlinConf Extended South Korea 2026 Keynote
l2hyunwoo
0
120
Featured
See All Featured
BBQ
matthewcrist
89
10k
We Are The Robots
honzajavorek
0
310
WCS-LA-2024
lcolladotor
0
800
Building an army of robots
kneath
306
46k
How To Speak Unicorn (iThemes Webinar)
marktimemedia
1
550
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Hiding What from Whom? A Critical Review of the History of Programming languages for Music
tomoyanonymous
3
1.1k
Crafting Experiences
bethany
1
260
How to Ace a Technical Interview
jacobian
281
24k
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
SERP Conf. Vienna - Web Accessibility: Optimizing for Inclusivity and SEO
sarafernandez
2
1.6k
Transcript
レンダリングしていますを 改善する
自己紹介 ▣ 石井直貴 □ NAVITIME 2010〜 ▣ Androidアプリ開発 □ NAVITIME,
乗換NAVITIME □ ここ地図 ( 8月リリース ) ▣ 趣味 □ ライブ鑑賞 □ 個人アプリ開発
今日話すこと ▣ レンダリングしています ▣ 調査方法 ▣ 改善したこと ▣ まとめ
注: ▣ パフォーマンス改善中です ▣ 今後のアップデートにご期待下さい!
レンダリングしています
レンダリングしています
レンダリングしています ▣ Android Vitalsの指標の1つ ▣ 主な指標には入っていない □ 主な指標 ▪ 過剰なウェイクアップ
▪ クラッシュ発生率 ▪ ANR発生率 ▣ 遅い表示・フリーズしたフレームがある
遅い表示 50% を超えるフレームで表示に要する時間が 16 ミリ秒を 上回った 1 日のセッションの割合(%)です。 1000ms /
60frames = 16.6666ms / frame
フリーズしたフレーム 0.1% を超えるフレームで表示に要する時間が 700 ミリ秒 を上回った 1 日のセッションの割合(%)です。
レンダリングしています - まとめ ▣ わかる数値 □ アプリ全体で遅いレンダリング・フリーズしたフレームの継続的 な数値 ▣ できること
□ この数値を追うことで、リリース毎にレンダリングパフォーマンス を意識することができる
どこの画面が遅いのかを知る
どこの画面が遅いのか Firebase Performance Monitoring
Firebase Performance Monitoring ▣ 2018 Google I/O 〜 betaを抜けてGAに ▣
Activityの計測は自動
Firebase Performance ▣ Activityの自動トレース ▣ build.gradleに記述するだけ classpath 'com.google.firebase:firebase-plugins:1.1.5' build.gradle (project)
apply plugin: 'com.google.firebase.firebase-perf' implementation 'com.google.firebase:firebase-perf:16.1.0' build.gradle (app)
Firebase Performance ▣ Activity毎に遅いレンダリング・フリーズしたフレームが 出る
どこの画面が遅いのか MultiActivity-App 1Activity-App
どこの画面が遅いのか (1Activity-App)
どこの画面が遅いのか (1Activity-App) ▣ Firebase Performanceのカスタムトレースを使う
Trace myTrace : Trace = FirebasePerformance.startTrace("test_trace") item : Item =
cache.fetch("item") if (item != null) { myTrace.incrementMetric("item_cache_hit", 1) } myTrace.stop() 開始 カウント 停止
Activityの自動計測をどのようにやっているか com.google.android.gms.internal.firebase-perf.zze ▣ ActivityLifecycleCallbacks使ってる ▣ onActivityStarted / onActivityStoppedで計測開始/停 止 ▣
16(ms), 700(ms)の条件でカウントしている これっぽい。。
やっている処理 ▣ onActivityStarted □ Traceをstart □ FrameMetricsAggregatorにActivityをAdd ▣ onActivityStopped □
FrameMetricsAggregatorからActivityをremoveし計測 値を取得 □ 取得した計測値を加工してTraceのカウントを増やす □ Traceをstop
FrameMetrics ▣ FrameMetricsListener API □ UI レンダリング パフォーマンスを監視 □ adb
shell dumpsys gfx infoと同じ内容. ▪ 最新の120 フレームに制限されない ▪ adb 接続不要 □ Android7.0(N)から ▪ そのため、AndroidVitalsではOS7.0以上の値しか表示 されない(6系も選択できるが) https://developer.android.com/about/versions/nougat/android-7.0?hl=ja#framemetrics_api
FrameMetricsAggregator ▣ FrameMetricsをまとめた値を取得できる ▣ Support Library 26.1.0〜
FragmentLifecycleCallbacksで実装 override fun onFragmentStarted(fm: FragmentManager, f: Fragment) { super.onFragmentStarted(fm, f)
val frameMetricsAggregator = FrameMetricsAggregator().apply { add(f.requireActivity()) } val trace = FirebasePerformance.startTrace(f.javaClass.simpleName) fragmentAggregatorMap[f] = frameMetricsAggregator fragmentTraceMap[f] = trace } https://github.com/iiinaiii/AndroidPerformanceSample FragmentPerformanceTracer.kt
override fun onFragmentStopped(fm: FragmentManager, f: Fragment) { ・・・ val collectedMetrics
= frameMetricsAggregator?.remove(f.requireActivity()) collectedMetrics?.get(0)?.let { totalDuration -> for (i in 0 until totalDuration.size()) { val frameDuration = totalDuration.keyAt(i) val sampleNum = totalDuration.valueAt(i) if (frameDuration > 700) { frozenFrameCount += sampleNum } if (frameDuration > 16) { slowRenderingCount += sampleNum } } } // 遅いレンダリングだったフレーム数 if (slowRenderingCount > 0) { trace?.incrementMetric(SLOW_RENDERING_COUNT, slowRenderingCount.toLong()) } trace?.stop() } metrics : SparseArray {6=3, 7=11, 8=1, 9=1, 11=1,12=1, 25=1, 40=1, 87=1} 6ms → 3frame 7ms → 11frame 8ms → 1frame …
レンダリングしています - Fragment ▣ 「時間」に出力
▣ 詳細で確認可 □ フレーム数 □ フリーズした フレーム数 □ フリーズした フレームの割合
□ 遅いレンダリングフ レーム数 □ 遅いレンダリングフ レームの割合 フレーム数 フリーズしたフ レーム数 フリーズしたフレー ムの割合(%) 遅いレンダリン グフレーム数 遅いレンダリン グフレームの割 合(%) レンダリングしています - Fragment
▣ 一覧に遅いレンダリング・フリーズしたフレームが出ないので 画面間の比較がしづらい ▣ 詳細に行けば見れるので、画面毎の数値が見れるのは良さそ う ▣ Activity.getWindowに対してのFrameMetricsなので、 Fragment単体でのレンダリング数値でないことに注意 ▣
どの画面(Fragment)が出ているときに数値が悪いかはわか る レンダリングしています - Fragment
どの画面が遅いのかを知る - まとめ ▣ わかる数値 □ 画面単位で遅い箇所 ▣ できること □
サンプル数と、遅いレンダリング or フリーズしたフレームの値か ら、改修優先度を決めることができる
画面内のどこが遅いのかを知る
画面内のどこが遅いか ▣ Hierarchy Viewer ▣ GPUレンダリングのプロファイル ▣ Systrace
Systrace https://developer.android.com/studio/command-line/systrace • platform-tools配下にあるツール • CPU利用状況やUIスレッドの処理内容/時間が見れる • Android Studio 3.2〜
Profilerで見れる
Systrace - 調査の流れ • Alertをチェック • 問題のある箇所がハイラ イト
• 遅いFrameをチェック • > 16.6ms Systrace - 調査の流れ • 遅い処理を調査
問題のある箇所の修正 • Expensive measure/layout pass → レイアウト階層の見直しとか • Long View#draw()
→ CustomViewのonDrawで時間のかかる処理して ないかとか
Systrace - favicon ▣ 遅いFrameの割合で faviconの色が違う □ 赤 → 30%より大きい
□ 黃 → 5% 〜 30% □ 緑 → 5%以下 const portionBad = badFramesObserved / framesObserved; if (portionBad > 0.3) { this.model.faviconHue = 'red'; } else if (portionBad > 0.05) { this.model.faviconHue = 'yellow'; } else { this.model.faviconHue = 'green'; } https://github.com/catapult-project/catapult/blob/maste r/tracing/tracing/extras/android/android_auditor.html
override fun bind(viewBinding: RouteResultItemFooterBinding, position: Int) { try { Trace.beginSection("RouteFooterItem.bind")
registerAdditionalInfoReceiver(viewBinding.root.context) try { Trace.beginSection("RouteFooterItem.bind.setupAroundCoupon") setupAroundCoupon(viewBinding) } finally { Trace.endSection() } ・・・ } finally { Trace.endSection() } } android.os.Trace • 開始 → Trace.beginSection(“名前”) • 停止 → Trace.endSection() Systrace - 注目したい場所に名前を付ける
Systrace - 注目したい場所に名前を付ける RouteFooterItem.bind RouteFooterItem.bind.setupAroundCoupon
Systrace - 操作 いっぱいある。。
Systrace - 操作 Select mode • 要素の選択 • cmd or
dragで複数要素選択 • ダブルクリックで同じ名前の要素全選択 基本的にはこのモードだけでOK 他のモードはショートカットで代替する (mode切替が煩わしいため)
Systrace - 操作 Pan • Viewの上下左右移動 • ショートカットキー ◦ a
→ 左へ移動 ◦ d → 右へ移動 ◦ shift + a/d で大きく移動 ◦ 上下はスクロールで Zoom • ズーム • ショートカットキー ◦ w → ズームイン ◦ s → ズームアウト ◦ f → 選択した要素にフォーカスズーム
Systrace - 操作 Timing • ハイライト • その箇所にかかった時間が見れる • ショートカットキー
◦ m → 選択している要素のハイライト
画面内のどこが遅いのかを知る - まとめ ▣ わかる数値 □ どの処理が遅いか ▣ できること □
具体的なコードの改修ができる
改善例
改善したこと ルート結果画面を RecyclerView化しました
× 3
ルート結果のレンダリング改善 Before After
RecyclerView化に際して ▣ 既存画面のリファクタリング(表示パターン多) □ Groupie □ 表示要素毎にItem分け. 表示パターンはItem内で吸収. ▣ パフォーマンス
□ RecycledViewPool □ ViewTypeを分けすぎないようまとめた
まとめ
レンダリングしていますを改善する - まとめ ▣ スケール別のレンダリング数値確認方法とできること □ アプリ全体の数値 ▪ Android Vitals
▪ リリース毎にレンダリングパフォーマンスを意識できる □ どの画面が遅いか ▪ Firebase Performance Monitoring ▪ 画面単位での改修優先度を決めることができる □ どの処理が遅いか ▪ Systrace(など) ▪ 具体的なコードの改修ができる
レンダリングしていますを改善する - まとめ ▣ 改善例 □ ルート結果の例
終