Slide 1

Slide 1 text

.PSJ"UTVTIJ גࣜձࣾαΠόʔΤʔδΣϯτגࣜձࣾ$ZCFS; ࣮ྫ͔ΒֶͿ 
 +FUQBDL$PNQPTFͷύϑΥʔϚϯεվળ %SPJE,BJHJ +FUQBDL$PNQPTF

Slide 2

Slide 2 text

株式会社サイバーエージェント 
 株式会社CyberZ OPENREC.tv 2019年度 未踏スーパークリエータ Mori Atsushi Twitter: @at_sushi_at

Slide 3

Slide 3 text

We Love 
 Jetpack Compose! Android向けの新しいUIフレームワーク 2019年 Google I/Oにて発表 2021年7⽉ Stable

Slide 4

Slide 4 text

パフォーマンス改善 ᶃNFBTVSF ᶄNFBTVSF ᶅNFBTVSF ᶆNFBTVSF ᶇNFBTVSF ᶃNFBTVSF ᶄNFBTVSF ᶅNFBTVSF "OESPJE7JFX +FUQBDL$PNQPTF 7JFX(SPVQ ਌$PNQPTBCMF 7JFX 7JFX ࢠ$PNQPTBCMF ࢠ$PNQPTBCMF ඞͣҰ౓ͣͭͷΈ͔͠ܭଌ͞Εͳ͍ ਌ࢠΛԿ౓΋ܭଌ͢Δ৔߹͕͋Δ

Slide 5

Slide 5 text

パフォーマンスの低下 Jetpack Composeのほうが 
 基本的にはパフォーマンスが良い ⼀⽅、予期せずパフォーマンスが落ちることがある スクロールやドラッグがもっさりしている アニメーションでフレーム落ちしている 操作に対する反応が遅れる 🐢

Slide 6

Slide 6 text

今回のゴール Jetpack Composeで陥りやすい 
 パフォーマンス低下を実例とともに理解/改善する 1. パフォーマンスの調査⽅法 2 . derivedStateOfを使う 3 . skippableにする 4 . Stateの監視場所を変える 🚀

Slide 7

Slide 7 text

パフォーマンスの調査⽅法 1

Slide 8

Slide 8 text

買い物リストアプリ 購⼊予定のアイテムを追加、管理できる 全体的に動作がもっさり… IUUQTHJUIVCDPN.PSJ"UTVTIJDPNQPTFQFSGPSNBODF

Slide 9

Slide 9 text

εΫϩʔϧҐஔ͸ ϦετͷҰ൪্͔ Ұ൪্Ͱͳ͍ͱ͖͸ "QQ#BSʹӨΛ͚ͭΔ εΫϩʔϧ͕͔ͭ͘͘ ഒ଎

Slide 10

Slide 10 text

早すぎる最適化を避ける க໋తͳ ύϑΥʔϚϯε՝୊ ίʔυͷՄಡੑ Өڹͷখ͍͞ ύϑΥʔϚϯε՝୊ Өڹͷͳ͍ ύϑΥʔϚϯε՝୊ ॏཁ౓͕ߴ͍ ॏཁ౓͕௿͍ 最初から最適化を⽬指すのは、コードの⾒通しが悪化したり、 
 無駄なコストになる パフォーマンスの問題が⽣じた際に必要な対応を⾏う

Slide 11

Slide 11 text

ボトルネックを探す 闇雲にコードを変更しても、解決に⾄る可能性は低く、 
 かえって問題を⼤きくする ボトルネックを発⾒し、解消することが重要である $PNQPTBCMF $PNQPTBCMF $PNQPTBCMF $PNQPTBCMF Composable 2 に時間がかかってるのに、1や3,4を頑張って変更しても、ほとんど変化はない

Slide 12

Slide 12 text

パフォーマンス問題が 
 ⽣じたら? 1. リリースビルドで確認する 2. 不要なRecomposeがないか確認する 3 . Pro fi lerで詳細を⾒る 🏃

Slide 13

Slide 13 text

1. リリースビルドで 
 1. 確認する Jetpack Composeはデバッグビルドと 
 リリースビルドで⼤きくパフォーマンスが異なる 不要なコードを削除するR 8 コンパイラも利⽤する (デフォルトで有効) 🛠 IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFQFSGPSNBODF

Slide 14

Slide 14 text

2. 不要なRecomposeがないか確認する $PNQPTBCMF ᶄ஋͕มԽ ᶃϘλϯ͕ΫϦοΫ ᶅ࠶࣮ߦ -FBWF &OUFS 3FDPNQPTF IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFMJGFDZDMF

Slide 15

Slide 15 text

ログを仕込む 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 4IPQQJOH-JTU1BHFDPNHJUIVCNPSJBUTVTIJQFSGPSNBODF%SFDPNQPTF 3FDPNQPTFຖʹ ϩάग़ྗ ࿈ଓతʹݺͼग़͞Ε͍ͯΔ

Slide 16

Slide 16 text

Layout Inspector Compose 1 . 2 以降とAndroid Studio Dolphin以降を使うと Recompose数を確認できる IUUQTEFWFMPQFSBOESPJEDPNTUVEJPSFMFBTFTMJDPNQPTFDPVOUFS 4IPX3FDPNQPTJUJPO 
 $PVOUTΛ༗ޮʹ͢Δ

Slide 17

Slide 17 text

3FDPNQPTF਺ 3FDPNQPTF͕εΩοϓ͞Εͨ਺ େྔʹSFDPNQPTF͞Ε͍ͯΔ

Slide 18

Slide 18 text

3 . Pro fi lerで詳細を⾒る アプリを実⾏中のデバイスのCPUやメモリの状況を確認できる IUUQTEFWFMPQFSBOESPJEDPNTUVEJPQSP fi MFBOESPJEQSP fi MFS

Slide 19

Slide 19 text

$BMMTUBDL4BNQMF3FDPSEJOH େྔʹ3FDPNQPTF͕ ݺ͹Ε͍ͯΔ

Slide 20

Slide 20 text

ϦϦʔεϏϧυͰ΋1SPGJMFՄೳʹ͢Δ "OESPJE.BOJGFTUYNM

Slide 21

Slide 21 text

6*δϟϯΫ͕ൃੜ͍ͯ͠Δ 4ZTUFN5SBDF3FDPSEJOH SFDPNQPTFʹ ͕͔͔͍࣌ؒͬͯΔ

Slide 22

Slide 22 text

Composition Tracing Compose 1 . 3 (beta)以降とAndroid Studio Flamingo(preview)を 
 使うとリリースビルドでも確認できる! IUUQTNFEJVNDPNBOESPJEEFWFMPQFSTKFUQBDLDPNQPTFDPNQPTJUJPOUSBDJOHFDCBFB 4IPQQJOH*UFN3PX͕ େྔʹݺ͹Ε͍ͯΔ 4ZTUFN5SBDF3FDPSEJOH

Slide 23

Slide 23 text

derivedStateOfを使う 2

Slide 24

Slide 24 text

গ͠Ͱ΋εΫϩʔϧ͞ΕΔ౓ʹɺ ࠶ܭࢉ͞Ε͍ͯΔ

Slide 25

Slide 25 text

ܭࢉ݁Ռ͕มΘͬͨͱ͖ͷΈ 
 3FDPNQPTF͢Δ SFNFNCFS͸ඞਢ ഒ଎ ͔͖͕ͭ͘ݮͬͨ

Slide 26

Slide 26 text

skippableにする 3

Slide 27

Slide 27 text

ϘλϯͰ਺ྔͷ૿ݮ͕Մೳ ߋ৽ͨ͠ΞΠςϜҎ֎΋ 3FDPNQPTF͞Ε͍ͯΔ ഒ଎

Slide 28

Slide 28 text

-B[Z$PMVNO *UFN -B[Z$PMVNO *UFN $IBOHFE 4LJQ Item: 1 を変更 ⼊⼒に変更がなければスキップする 4LJQ 3FDPNQPTF *UFN *UFN *UFN 3FDPNQPTF

Slide 29

Slide 29 text

スキップの条件 条件1: すべての⼊⼒が安定している → 全く変更がされない(Immutable)か、 
 → 変更時にCompositionに通知される 条件2:すべての⼊⼒で変更がない → すべての⼊⼒でequalsの結果がtrue 🚅

Slide 30

Slide 30 text

スキップの条件 条件1: すべての⼊⼒が安定している → 全く変更がされない(Immutable)か、 
 → 変更時にCompositionに通知される 条件2:すべての⼊⼒で変更がない → すべての⼊⼒でequalsの結果がtrue 🚅

Slide 31

Slide 31 text

安定している型(抜粋) ϓϦϛςΟϒ஋ܕ จࣈྻ ϥϜμࣜ ͦΕΒͰߏ੒͞ΕΔෆมͳDMBTT

Slide 32

Slide 32 text

安定していない型(抜粋) -JTU4FU ՄมͳΫϥε $PNQPTFΛ࢖͍ͬͯͳ͍ ଞϞδϡʔϧϥΠϒϥϦͷΫϥε 5ISPXBCMF΍%BUF

Slide 33

Slide 33 text

Compose Compiler Metrics Composableがスキップ可能か確認できるツール ΦϓγϣϯΛ௥Ճ CVJMEDPNQPTF@NFUSJDTʹ Ϩϙʔτ͕ग़ྗ͞ΕΔ IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFMJGFDZDMF

Slide 34

Slide 34 text

҆ఆ͍ͯ͠ͳ͍ εΩοϓෆՄ ҆ఆ͍ͯ͠ͳ͍

Slide 35

Slide 35 text

ΞϊςʔγϣϯͰෆมͰ ͋Δ͜ͱΛ໌ࣔ

Slide 36

Slide 36 text

಺෦ʹ.VUBCMF4UBUF౳ͷՄม஋͕͋Δ৔߹͸ 4UBCMFΞϊςʔγϣϯΛར༻͢Δ ಺෦ͷ஋͕มΘΒͳ͍ͱ͖͸ *NNVUBCMFΛ࢖͏

Slide 37

Slide 37 text

案1 依存関係を追加して @Immutable / @Stable 
 を付与する モデルが別モジュールにある場合 案2 View⽤のmodelを別で作成し、 マッピングする 案3 @Immutable / @Stableを 
 つけたHolder classでwrapする

Slide 38

Slide 38 text

すべてをskippableに? 💡 すべてのComposbleをskippableにするのは、 
 早すぎる最適化のように感じる 同じ引数で再び呼び出されることのない Composableをskippableにするのは無意味である

Slide 39

Slide 39 text

スキップの条件 条件1: すべての⼊⼒が安定している → 全く変更がされない(Immutable)か、 
 → 変更時にCompositionに通知される 条件2:すべての⼊⼒で変更がない → すべての⼊⼒でequalsの結果がtrue 🚅

Slide 40

Slide 40 text

ຖճ-BNCEB͕ࣜ࠶ੜ੒͞Εɺ มߋ͕͋ΔͱΈͳ͞ΕΔ

Slide 41

Slide 41 text

Lambda式の再⽣成 ࠶ར༻͞ΕΔ ࠶ੜ੒͞ΕΔ Lambda式中で安定でないクラスを参照していると、 
 recompose毎にLambda式が再⽣成される IUUQTNVMUJUISFBEFETUJUDI fi YDPNCMPHKFUQBDLDPNQPTFSFDPNQPTJUJPO

Slide 42

Slide 42 text

Lambda式の再⽣成を防ぐ 案2 Lambda式を明⽰的に 
 rememberする 案3 関数参照を渡す 案1 ViewModelに@Stableを追加

Slide 43

Slide 43 text

ഒ଎ ߋ৽͞ΕͨΞΠςϜͷΈ SFDPNQPTF͞ΕΔ

Slide 44

Slide 44 text

Stateの監視場所を変える 4

Slide 45

Slide 45 text

εϥΠμʔͷ஋ Ҿ਺Ͱঢ়ଶΛड͚औΔ ഒ଎ εϥΠμʔ͕ॏ͍ͨ

Slide 46

Slide 46 text

State Hosting 4IPQQJOH-JTU1BHF "EE%JBMPH 4MJEFS 3FDPNQPTF 3FDPNQPTF 3FDPNQPTF 状態は呼び出し元で管理し、 Single Source of Truthを実現する ⼦をrecomposeするために、 すべての親がrecomposeされている IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFTUBUFTUBUFIPJTUJOH

Slide 47

Slide 47 text

Stateの監視とrecomposeの範囲 4UBUFͰड͚औΔ ͜͜Ͱ؂ࢹ ͜͜Ͱ؂ࢹ

Slide 48

Slide 48 text

-BNCEBࣜͰड͚औΔ 他の記述⽅法 ಠࣗ4UBUFΛ༻ҙ͢Δ

Slide 49

Slide 49 text

4UBUFͰอ࣋͢Δ ഒ଎ վળʂ

Slide 50

Slide 50 text

Stateの取得を遅らせる 🛫 必要になるまでStateの値の取得を遅らせることで、 必要最⼩限のスコープで再実⾏ができる skippableの対応のほうが体感効果が⾼い スクロール、ドラッグ、アニメーション等、 
 毎フレーム値が変わる場合におすすめ

Slide 51

Slide 51 text

まとめ $PNQPTJUJPO パフォーマンスはボトルネックを発⾒し、改善を⽬指す よくある修正⽅法 - derivedStateOfを使う - skippableにする - Stateの監視場所を変える パフォーマンスの調査⽅法 - 不要なrecomposeが - ないか確認する - Pro fi lerで詳細を⾒る