Upgrade to Pro — share decks privately, control downloads, hide ads and more …

実例から学ぶJetpack Composeのパフォーマンス改善

Mori Atsushi
October 06, 2022

実例から学ぶJetpack Composeのパフォーマンス改善

Jetpack ComposeはAndroid Viewシステムの教訓を経て、多くのケースで優れたパフォーマンスを発揮します。一方で、いつの間にかパフォーマンスが低下している経験をした人も多いのではないでしょうか?特にアニメーションの表現や、スクロールやドラッグの操作によってUIを切り替える際によく問題が発生します。これらは、必要以上の広範囲で高速に更新処理が行われることに起因します。

より良いパフォーマンスを得るには、Jetpack ComposeのUI更新の仕組みを理解し、状況に応じて対処していく必要があります。このセッションでは実例をもとに、パフォーマンス低下の原因、計測方法、改善方法について解説を行います。

DroidKaigi: https://droidkaigi.jp/2022/timetable/364831
Video: https://youtu.be/_kIkc4IBLHI
Sample code: https://github.com/Mori-Atsushi/compose-performance

Mori Atsushi

October 06, 2022
Tweet

More Decks by Mori Atsushi

Other Decks in Technology

Transcript

  1. .PSJ"UTVTIJ
    גࣜձࣾαΠόʔΤʔδΣϯτגࣜձࣾ$ZCFS;
    ࣮ྫ͔ΒֶͿ

    +FUQBDL$PNQPTFͷύϑΥʔϚϯεվળ
    %SPJE,BJHJ +FUQBDL$PNQPTF

    View Slide

  2. 株式会社サイバーエージェント

    株式会社CyberZ


    OPENREC.tv


    2019年度 未踏スーパークリエータ
    Mori Atsushi
    Twitter: @at_sushi_at

    View Slide

  3. We Love

    Jetpack Compose!
    Android向けの新しいUIフレームワーク


    2019年 Google I/Oにて発表


    2021年7⽉ Stable

    View Slide

  4. パフォーマンス改善
    ᶃNFBTVSF

    ᶄNFBTVSF
    ᶅNFBTVSF

    ᶆNFBTVSF
    ᶇNFBTVSF

    ᶃNFBTVSF

    ᶄNFBTVSF
    ᶅNFBTVSF

    "OESPJE7JFX +FUQBDL$PNQPTF
    7JFX(SPVQ ਌$PNQPTBCMF
    7JFX 7JFX ࢠ$PNQPTBCMF ࢠ$PNQPTBCMF
    ඞͣҰ౓ͣͭͷΈ͔͠ܭଌ͞Εͳ͍
    ਌ࢠΛԿ౓΋ܭଌ͢Δ৔߹͕͋Δ

    View Slide

  5. パフォーマンスの低下
    Jetpack Composeのほうが

    基本的にはパフォーマンスが良い


    ⼀⽅、予期せずパフォーマンスが落ちることがある


    スクロールやドラッグがもっさりしている


    アニメーションでフレーム落ちしている


    操作に対する反応が遅れる
    🐢

    View Slide

  6. 今回のゴール
    Jetpack Composeで陥りやすい

    パフォーマンス低下を実例とともに理解/改善する


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


    2
    . derivedStateOfを使う


    3
    . skippableにする


    4
    . Stateの監視場所を変える
    🚀

    View Slide

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

    View Slide

  8. 買い物リストアプリ
    購⼊予定のアイテムを追加、管理できる


    全体的に動作がもっさり…


    IUUQTHJUIVCDPN.PSJ"UTVTIJDPNQPTFQFSGPSNBODF

    View Slide

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

    View Slide

  10. 早すぎる最適化を避ける
    க໋తͳ
    ύϑΥʔϚϯε՝୊
    ίʔυͷՄಡੑ
    Өڹͷখ͍͞
    ύϑΥʔϚϯε՝୊
    Өڹͷͳ͍
    ύϑΥʔϚϯε՝୊
    ॏཁ౓͕ߴ͍ ॏཁ౓͕௿͍
    最初から最適化を⽬指すのは、コードの⾒通しが悪化したり、

    無駄なコストになる


    パフォーマンスの問題が⽣じた際に必要な対応を⾏う

    View Slide

  11. ボトルネックを探す
    闇雲にコードを変更しても、解決に⾄る可能性は低く、

    かえって問題を⼤きくする


    ボトルネックを発⾒し、解消することが重要である
    $PNQPTBCMF $PNQPTBCMF
    $PNQPTBCMF

    $PNQPTBCMF

    Composable
    2
    に時間がかかってるのに、1や3,4を頑張って変更しても、ほとんど変化はない

    View Slide

  12. パフォーマンス問題が

    ⽣じたら?
    1. リリースビルドで確認する


    2. 不要なRecomposeがないか確認する


    3
    . Pro
    fi
    lerで詳細を⾒る
    🏃

    View Slide

  13. 1. リリースビルドで

    1. 確認する
    Jetpack Composeはデバッグビルドと

    リリースビルドで⼤きくパフォーマンスが異なる


    不要なコードを削除するR
    8
    コンパイラも利⽤する
    (デフォルトで有効)
    🛠
    IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFQFSGPSNBODF

    View Slide

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

    View Slide

  15. ログを仕込む
    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ຖʹ
    ϩάग़ྗ
    ࿈ଓతʹݺͼग़͞Ε͍ͯΔ

    View Slide

  16. Layout Inspector
    Compose
    1
    .
    2
    以降とAndroid Studio Dolphin以降を使うと


    Recompose数を確認できる
    IUUQTEFWFMPQFSBOESPJEDPNTUVEJPSFMFBTFTMJDPNQPTFDPVOUFS
    4IPX3FDPNQPTJUJPO

    $PVOUTΛ༗ޮʹ͢Δ

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  22. Composition Tracing
    Compose
    1
    .
    3
    (beta)以降とAndroid Studio Flamingo(preview)を

    使うとリリースビルドでも確認できる!
    IUUQTNFEJVNDPNBOESPJEEFWFMPQFSTKFUQBDLDPNQPTFDPNQPTJUJPOUSBDJOHFDCBFB
    4IPQQJOH*UFN3PX͕
    େྔʹݺ͹Ε͍ͯΔ
    4ZTUFN5SBDF3FDPSEJOH

    View Slide

  23. derivedStateOfを使う
    2

    View Slide

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

    View Slide

  25. ܭࢉ݁Ռ͕มΘͬͨͱ͖ͷΈ

    3FDPNQPTF͢Δ
    SFNFNCFS͸ඞਢ
    ഒ଎
    ͔͖͕ͭ͘ݮͬͨ

    View Slide

  26. skippableにする
    3

    View Slide

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

    View Slide

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

    View Slide

  29. スキップの条件
    条件1: すべての⼊⼒が安定している


    → 全く変更がされない(Immutable)か、

    → 変更時にCompositionに通知される


    条件2:すべての⼊⼒で変更がない


    → すべての⼊⼒でequalsの結果がtrue
    🚅

    View Slide

  30. スキップの条件
    条件1: すべての⼊⼒が安定している


    → 全く変更がされない(Immutable)か、

    → 変更時にCompositionに通知される


    条件2:すべての⼊⼒で変更がない


    → すべての⼊⼒でequalsの結果がtrue
    🚅

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  37. 案1


    依存関係を追加して
    @Immutable / @Stable

    を付与する
    モデルが別モジュールにある場合
    案2


    View⽤のmodelを別で作成し、
    マッピングする
    案3


    @Immutable / @Stableを

    つけたHolder classでwrapする

    View Slide

  38. すべてをskippableに?
    💡 すべてのComposbleをskippableにするのは、

    早すぎる最適化のように感じる


    同じ引数で再び呼び出されることのない
    Composableをskippableにするのは無意味である

    View Slide

  39. スキップの条件
    条件1: すべての⼊⼒が安定している


    → 全く変更がされない(Immutable)か、

    → 変更時にCompositionに通知される


    条件2:すべての⼊⼒で変更がない


    → すべての⼊⼒でequalsの結果がtrue
    🚅

    View Slide

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

    View Slide

  41. Lambda式の再⽣成
    ࠶ར༻͞ΕΔ
    ࠶ੜ੒͞ΕΔ
    Lambda式中で安定でないクラスを参照していると、

    recompose毎にLambda式が再⽣成される
    IUUQTNVMUJUISFBEFETUJUDI
    fi
    YDPNCMPHKFUQBDLDPNQPTFSFDPNQPTJUJPO

    View Slide

  42. Lambda式の再⽣成を防ぐ
    案2


    Lambda式を明⽰的に

    rememberする
    案3


    関数参照を渡す
    案1


    ViewModelに@Stableを追加

    View Slide

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

    View Slide

  44. Stateの監視場所を変える
    4

    View Slide

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

    View Slide

  46. State Hosting
    4IPQQJOH-JTU1BHF
    "EE%JBMPH
    4MJEFS
    3FDPNQPTF
    3FDPNQPTF
    3FDPNQPTF
    状態は呼び出し元で管理し、


    Single Source of Truthを実現する


    ⼦をrecomposeするために、


    すべての親がrecomposeされている
    IUUQTEFWFMPQFSBOESPJEDPNKFUQBDLDPNQPTFTUBUFTUBUFIPJTUJOH

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  50. Stateの取得を遅らせる
    🛫 必要になるまでStateの値の取得を遅らせることで、


    必要最⼩限のスコープで再実⾏ができる


    skippableの対応のほうが体感効果が⾼い


    スクロール、ドラッグ、アニメーション等、

    毎フレーム値が変わる場合におすすめ

    View Slide

  51. まとめ
    $PNQPTJUJPO
    パフォーマンスはボトルネックを発⾒し、改善を⽬指す


    よくある修正⽅法


    - derivedStateOfを使う


    - skippableにする


    - Stateの監視場所を変える
    パフォーマンスの調査⽅法


    - 不要なrecomposeが


    - ないか確認する


    - Pro
    fi
    lerで詳細を⾒る

    View Slide