Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
Compose の LazyColumn パフォーマンス改善で取り組んだこと
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
Tomoya Miwa
June 14, 2022
Technology
2.5k
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Compose の LazyColumn パフォーマンス改善で取り組んだこと
sample source:
https://github.com/tomoya0x00/ComposeLazyColumnSandbox
Tomoya Miwa
June 14, 2022
More Decks by Tomoya Miwa
See All by Tomoya Miwa
基礎から学ぶ大画面対応(Learning Large-Screen Support from the Ground Up)
tomoya0x00
0
8.3k
Re:VIEWで書いた「Compose で Android の edge-to-edge に対応する」をRoo Codeで発表資料にしてもらった
tomoya0x00
0
720
Compose 1.7のTextFieldはPOBox Plusで日本語変換できない
tomoya0x00
0
490
できる!ComposeでCollapsingToolbar
tomoya0x00
0
1.1k
ComposeのMutableStateってどうやってLocal Unit Testすれば良いの??
tomoya0x00
0
1.3k
意外と簡単?Navigation rail導入のお話
tomoya0x00
0
1.6k
Kotlin Coroutines Flow を触ってみた話し
tomoya0x00
2
910
Android for Carsのお話し
tomoya0x00
1
1.1k
熟成されたアプリのmulti module化(halfway)
tomoya0x00
2
1.1k
Other Decks in Technology
See All in Technology
アリアドネの糸と、20年ごとの建て替え ── 長尾真『電子図書館』を、伊勢で読み直す / Rereading Makoto Nagao’s "Electronic Library" in Ise
ykiyota
0
150
2026_devsumi_ozono.pdf
o3
2
300
Oracle Cloud Infrastructure IaaS 新機能アップデート 2026/6 - 2026/8
oracle4engineer
PRO
0
140
なぜSRE・セキュリティは評価されないのか?守りの組織を事業成長エンジンに変えた実践
cscengineer
PRO
3
2.4k
Omarchy Quattro の日本語設定周り
simosako
2
140
Snowflakeで実現する全社横断の顧客の声(VOC)分析・活用基盤@Snowflake World Tour Tokyo 2026
yuto16
0
160
The Agent Builder Loop from Daily Work to OSS
minorun365
PRO
3
120
HRC_Frontend_Conference_Fukuoka_2026.pdf
ts020
0
370
プロダクト思考 × 基盤思考を AIで実現する Compound Engineering
tkc66buzz
1
310
Screen Lens - 今見てる画面を翻訳する
komagata
0
230
コーディングエージェントでM5Stack系の開発を少し試した時の話 / M5 Japan Tour 2026 Autumn 東京
you
PRO
0
130
あるけみー式LTスライド作成術
alchemy1115
1
170
Featured
See All Featured
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
820
Navigating the Design Leadership Dip - Product Design Week Design Leaders+ Conference 2024
apolaine
2
420
Designing Dashboards & Data Visualisations in Web Apps
destraynor
232
55k
The agentic SEO stack - context over prompts
schlessera
0
920
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
680
Unlocking the hidden potential of vector embeddings in international SEO
frankvandijk
0
930
Why You Should Never Use an ORM
jnunemaker
PRO
61
10k
WENDY [Excerpt]
tessaabrams
13
39k
Speed Design
sergeychernyshev
33
2.1k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
Exploring anti-patterns in Rails
aemeredith
3
500
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Transcript
Compose の LazyColumn パフォーマンス改善で取り組 んだこと 2022/06/14 Engineer LT#1 Android tomoya0x00
1
About me tomoya0x00 Twitter, GitHub Android U-NEXT Co., Ltd. 2
今回のLTが(もしかしたら)役に立つかもしれない? LazyColumnって、RecyclerViewよりもパフォーマンス良いんだよね? Composeのパフォーマンス問題って、Releaseビルドにしたら解決するんでしょ? 最新技術のComposeなんだから、従来のAndroid Viewよりもパフォーマンスで悩むこと は少ないはず! 3
お話しすること LazyColumnを気軽に使ったらパフォーマンス問題に直面し、 なんとかNexus 7 2013という低スペック端末でもある程度使えるレベルにした話。 4
目次 パフォーマンスに絶望した話 パフォーマンス問題に対する考察 対策その1: Glideを使ってみる 対策その2: さらにインスタンス生成を減らす 対策その3: 描画を遅延させてスキップ可能とする これまでのような対策の前に確認しておくと良い事
他にも効果がありそうな事 まとめと感想 5
パフォーマンスに絶望した話 6
まずは動画をご覧下さい 7
8
パフォーマンスに絶望した話 Nexus 7 2013で動かしました アニメーションGIFのフレームレートは30fpsです アニメーションGIFだからカクカクしているわけではありません Releaseビルドです もちろん、minifyEnabled true LazyRow
in LazyColumnで、各itemではCard内でCoilにより画像表示しているだけのシ ンプルなアプリです ちなみに、RecyclerViewだとさくさく動きます ソースコードのリンク: MainContentA 9
このままだとCompose化の夢が絶たれてしまう・・・ 10
パフォーマンス問題に対する考察 11
logcat GCのログが多いような気がする Background partial concurrent mark sweep GC freed 12609(781KB)
AllocSpace objects, 9(180KB) LOS objects, 39% free, 21MB/35MB, paused 5.401ms total 73.333ms Background partial concurrent mark sweep GC freed 9126(463KB) AllocSpace objects, 3(156KB) LOS objects, 33% free, 31MB/47MB, paused 7.476ms total 48.278ms Background partial concurrent mark sweep GC freed 122448(9MB) AllocSpace objects, 0(0B) LOS objects, 33% free, 24MB/36MB, paused 3.021ms total 171.936ms Background partial concurrent mark sweep GC freed 34312(1960KB) AllocSpace objects, 1(20KB) LOS objects, 33% free, 23MB/35MB, paused 1.861ms total 110.321ms Background partial concurrent mark sweep GC freed 302696(15MB) AllocSpace objects, 5(124KB) LOS objects, 36% free, 28MB/44MB, paused 2.227ms total 140.014ms Background partial concurrent mark sweep GC freed 95715(7MB) AllocSpace objects, 4(80KB) LOS objects, 33% free, 24MB/36MB, paused 1.861ms total 106.079ms ... 12
パフォーマンス問題に対する考察 Nexus 7 2013という(今となっては)低スペック端末にとっては、 インスタンス生成が走りすぎているのかも知れない。 CoilのAsyncImageは色々インスタンス生成している 各AsyncImageごとにcoroutineを起動しているっぽい? その他、色々インスタンス生成している Modifierもメソッドチェーンする度に新しいインスタンスを生成しているっぽい 確かにAsyncImage無しだとかなりパフォーマンスが改善したので、
まずはCoil使うのをやめてみる。 ※ 一般的なケースでは、Coilがボトルネックになることは無いとおもいます!! 13
対策その1: Glideを使ってみる 14
対策その1: Glideを使ってみる Glide版の画像読み込みComposableをつくってみた。 以前はaccompanistでComposable版が提供されていた実績がある 昔からあるライブラリだから、使用するリソース的にも優しいはず 確かにパフォーマンスは改善したけど、まだカクついてる。 ソースコードのリンク: MainContentBSimpleAsyncImage 15
対策その2: さらにインスタンス生成を減らす 徹底的にインスタンス生成を減らす。 MaterialのCard使うのをやめる 内部で色々インスタンス生成しているため 一度つくったModifierはキャッシュする ソースコードのリンク: MainContentC 16
Modifierのキャッシュ class ModifierCacheHolder { private val map = mutableMapOf<String, Modifier>()
@SuppressLint("ModifierFactoryExtensionFunction", "ComposableModifierFactory") @Composable fun getOrCreate( tag: String, creator: @Composable () -> Modifier, ): Modifier = map[tag] ?: creator.invoke().also { map[tag] = it } } ソースコードのリンク: ModifierCacheHolder 17
Modifierのキャッシュ val modifierCacheHolder = remember { ModifierCacheHolder() } Column( modifier
= modifierCacheHolder.getOrCreate(tag = "MainRowRoot") { Modifier.padding(top = 8.dp) }, ) { ... } 18
Modifierのキャッシュ 基本的にModifierのインスタンスはStableなので、使い回しても大丈夫・・・なはず ただし、あんまり自信は無し 今のところ目に見えて不具合は起きていないので、たぶん大丈夫? ただし、Modifier.clickable()のインスタンスはキャッシュしちゃダメ 最初にセットしたクリックリスナーが使い回されてしまう clickable()の手前までのModifierのインスタンスなら、キャッシュしてOK 19
改善の成果をご覧下さい 20
21
残った課題に対する考察 22
残った課題に対する考察 高速なスクロールは、とてもカクつく 各行の描画にかかる時間が、そもそも1フレームを超えていそう そもそも高速スクロールで一瞬しか表示されないなら、描画をサボって良いのでは? 描画自体を遅延させてスキップ可能にしてみてはどうだろう? ソースコードのリンク: MainContentD 23
対策その3: 描画を遅延させてスキップ可能とする 24
対策その3: 描画を遅延させてスキップ可能とする @Composable fun LazyBox( modifier: Modifier = Modifier, delayMilliSec:
Long, content: @Composable BoxScope.() -> Unit, ) { Box( modifier = modifier, ) { var showContent by remember { mutableStateOf(false) } LaunchedEffect(Unit) { withContext(Dispatchers.Default) { delay(delayMilliSec) showContent = true } } if (showContent) content.invoke(this) } } ソースコードのリンク: LazyBox 25
対策その3: 描画を遅延させてスキップ可能とする LazyBox( delayMilliSec = 10, placeHolder = { Spacer(
modifier = modifierCacheHolder.getOrCreate(tag = "MainRowPlaceHolder") { Modifier.size(8.dp * 2 + 120.dp * 9f / 16) }, ) }, ) { LazyRow { items( items = data.rowIds, key = { it }, ) { rowId -> MainItemD( modifierCacheHolder = modifierCacheHolder, text = "${data.columnId}_$rowId", ) } } } 26
最終的にどうなったか 27
28
これまでのような対策の前に確認しておくと良い事 29
これまでのような対策の前に確認しておくと良い事 Compose Compiler Metricsのチェック https://github.com/androidx/androidx/blob/androidx- main/compose/compiler/design/compiler-metrics.md 特にListはそのままだとStable扱いにならないので要注意です 対策の例としては、@Immutableなdata classで包む Jetpack
ComposeのComposable関数の引数に別のモジュールのクラスを使うときの注 意点 https://qiita.com/takahirom/items/6907e810d3661e19cfcf 30
他にも効果がありそうな事 31
他にも効果がありそうな事 Compose 1.2のcontentType LazyListでRecyclerViewのようにComposableをもっと効率的に再利用するための もの ただし、今回の例に適用してもあまり効果が感じられなかった 使い方が悪い?ちゃんと計測したら、実は改善されているのかも? Baseline Profiles あらかじめよく使うパスを計測しておくことで、それらのバイトコードからコンパ
イルしてもらう、というもの? 効果が期待できそうだけど、まだ試せておらず 32
まとめと感想 33
まとめと感想 正直、やり過ぎたと思ってます たぶん、通常のアプリだとどうしても必要な場合だけLazyBoxいれる、ぐらいで良 いと思う そもそもBaseline Profilesで事足りるかも知れない 今時、Nexus 7 2013は流石に考慮しなくて良いと思う ただし、特にお手頃価格のタブレットはパフォーマンスが控えめな事もあるので、
実機で動作確認してみた方が良い 34