Lock in $30 Savings on PRO—Offer Ends Soon! ⏳

アニメーションを最深まで理解してパフォーマンスを向上させる

mine2424
November 22, 2024

 アニメーションを最深まで理解してパフォーマンスを向上させる

概要
Flutter でのアニメーション実装は、簡易に実装できてアプリの魅力を向上させる重要な機能ですが、複雑なアニメーションや大規模なアプリケーションでは、パフォーマンスの問題に直面することがあります。
複雑なアニメーションを実装する際、フレームレートの低下やメモリ使用量の増加など、パフォーマンスの低下が課題となっています。また、アニメーションの最適化手法や、適切なタイミングでの RepaintBoundary の使用など、開発者が理解すべき点が多岐にわたります。

本セッションでは、 Flutter のアニメーションを深く理解し、パフォーマンスを向上させるための実践的な手法を紹介します。 Flow を活用した複雑なアニメーションの実装、アニメーションのパフォーマンス最適化テクニック、そしてレンダリングを最小限に抑えるための tips について詳しく解説します。
1.Flutter アニメーションの基本概念と内部実装を理解する
2.Flow を使用した高度なアニメーションの実装手法
3.アニメーションパフォーマンスの測定と分析
4.レンダリング最適化テクニック

想定視聴者
・ 複雑なアニメーションの実装に苦戦している開発者
・ アニメーションのパフォーマンス向上に興味がある開発者

mine2424

November 22, 2024
Tweet

More Decks by mine2424

Other Decks in Programming

Transcript

  1. 株式会社サイバーエージェント 
 SGEマンガ事業部 モバイルエンジニア
 みね
 @mine2424 @nihon_kaizou 2024年度新卒入社
 大学1年から Flutter

    によるアプリ開発を開始 
 
 # F1 # 麻雀 # 海外旅行 (9割カジノ) # 来年ポーカーの世界大会出場します 
 Nishimine Ryota

  2. テーマ選定理由と直近の動向 
 01
 アニメーション周りの動向 
 ・Impeller の stable 化 ・Lottie

    や Rive 等の複雑なパスの計算の向上 (by Impeller)
 
 ・Blur のパフォーマンス向上 (by Impeller)
  Blur の再実装により CPU, GPU の使用率が半分程度まで抑えられた 

  3. テーマ選定理由と直近の動向 
 01
 Shader Compilation Jank
 ・Shader Compilation Jank とは?

     アニメーションが初回起動時に発生するパフォーマンス低下を起こす問題 
 
 ・Skia 時代  コンパイル時に必要な Shader が widget の描画と同時に生成されるため 
 パフォーマンスの低下を引き起こしていた 
 
 ・Impeller 時代  アニメーションビルド時に必要な Shader を生成するため、
 コンパイル中に発生する Shader Jank を防ぐことができる 

  4. テーマ選定理由と直近の動向 
 01
 Stencil-then-Cover Approach
 ・課題
  すべての描画パスを CPU で分割し、その後 GPU

    に送信して描画します。
 しかしこれでは CPU に大きな負荷をかけパフォーマンスが低下する可能性があった。 
 
 ・解決策
  描画したい形をあらかじめ Stencil Buffer に書き込み必要な部分だけ描画することで、 
 無駄な描画を最低限にすることができる。 
 

  5. Flutter アニメーション入門 
 アニメーション Widget の種類
 02
 ・Implicit / Explicit

    Animation  主に AnimationController を利用して Widget の挙動を操作する ・Low Level Animation
  CustomPainter を利用して Canvas に描画されるものに対してパラメータを操作することで 
 Widget の挙動を操作する
 
 ・Third Party Animation Framework
  Lottie や Rive といったフレームワークによるアニメーション表現を行う 

  6. Flutter アニメーション入門 
 アニメーション Widget の種類
 02
 ・Implicit Animation  Widget

    の property の値が変更された際にアニメーションを行う 
 AnimationController を使用せずに Widget が使える (AnimatedFoo 系)
 ・Explicit Animation
  AnimationController や Tween を用いて詳細にアニメーションの設定を行うことができる 
 (FooTransition 系)

  7. Flutter アニメーション入門 
 Explicit Animation
 02
 Tween は animation の


    開始と終了の値を定義する
 
 animate() で controller と
 紐付けられる
 アニメーションを開始

  8. Flutter における Animation の仕組み
 Deep Dive Animation
 03
 ・Animation class

     アニメーションにおける現在の値 (value) と AnimationStatus のみを保持する
  Listenable を継承しているので AnimationController 等で value や AnimationStatus の変化を
 検知することができる。

  9. Flutter における Animation の仕組み
 Deep Dive Animation
 03
 ・AnimationController  Animation

    を継承したクラスで自身が持つメソッドで管理している値を制御できる 
  forward(), reverse(), stop() etc …

  10. Flutter における Animation の仕組み
 Deep Dive Animation
 03
 ・Ticker
  1

    frame ごとに callback を呼ぶ
 
 ・vsync
  frame を画面のリフレッシュ・レートに 
 同期させることで視覚的な歪みを防いでいる。 
 
 

  11. What is Ticker ?
 ・SchedulerBinding について
  アプリの動作をデバイスのディスプレイの frame と同期させる
 ex)

    30 FPS = 30 frame / sec
 Deep Dive Animation
 03
 30 FPS 60 FPS 120 FPS Old Phone iPhone 8 iPhone 16 Pro
  12. What is Ticker ?
 Deep Dive Animation
 03
 Event SchedulerBinding


    を介して通信
 Flutter Engine Ticker SchedulerBinding
 SchedulerBinding を介して
 毎 frame ごとにイベントが送られるが 
 Ticker で Animation を行うかを制御する

  13. What is Ticker ?
 Deep Dive Animation
 03
 Event SchedulerBinding


    を介して通信
 Flutter Engine Ticker SchedulerBinding
 SchedulerBinding を介して
 毎 frame ごとにイベントが送られるが 
 Ticker で Animation を行うかを制御する
 Paint
  14. Flutter における Animation の仕組み
 Deep Dive Animation
 03
 ・Ticker
  1

    frame ごとに callback を呼ぶ
 
 ・vsync
  frame を画面のリフレッシュ・レートに 
 同期させることで視覚的な歪みを防いでいる。 
 
 

  15. SingleTickerProviderStateMixin
 Deep Dive Animation
 03
 ・対象の Widget tree が有効な場合に単一の Ticker

    を更新する mixin ・継承先の class で単一の AnimationController を使用する際に使用( vsync: this で使用)

  16. SingleTickerProviderStateMixin
 Deep Dive Animation
 03
 ticker を現在の Widget tree 内で

    有効にするかのフラグを管理 
 ticker 自身を管理

  17. パフォーマンスの計測と分析 
 パフォーマンスの計測方法 
 04
 ・DevTools の活用
 ・Flutter Inspector
  UI

    のレイアウトや widget のプロパティを確認できる 
 ・Performance View
  アプリのパフォーマンスをリアルタイムで監視し、 CPUやメモリの使用状況を分析 
 ・Memory View
  メモリ使用量の時系列グラフ表示や、メモリインスタンスの分析を行う
  18. パフォーマンスの計測と分析 
 DevTools の見方
 04
 ・Frame Chart  1 frame =

    1つのバーとして扱い、フレームのレンダリング中に発生する 
 それぞれの役割の作業によってバーの色が異なる 

  19. パフォーマンスの計測と分析 
 DevTools の見方
 04
 ・Raster Thread  Skia や Impeller

    といった Flutter Engine からグラフィックコードを実行するもの。 
 なので UI Thread でのアプリケーションロジックの実行とは別で扱う。 
 (簡単に言えば、GPU の処理に関する Thread)

  20. パフォーマンスの計測と分析 
 DevTools の見方
 04
 ・Jank  frame のレンダリングが 16 ms

    以上 かかる場合に Jank としてみなされこの色になります 
 : frame 内で Jank が
 発生した箇所
 (60 FPS のデバイスの場合 )
  21. パフォーマンスの計測と分析 
 計測時の注意点 
 04
 ・パフォーマンス計測時は Profile Mode で実行すること 


    ・実行の違い 
 Debug : JIT (just in time) その場で compile される Profile : AOT (ahead of time) アプリが読み込まれる前にpre-compile されて実行
  22. パフォーマンスの計測と分析 
 計測結果
 04
 ・Paint Time
 196.763 ~ 196.780 s

    => 0.17s (170 ms)  
 1frame ~ 16 ms 以下に抑えられていない 

  23. パフォーマンスの計測と分析 
 計測結果
 04
 ・Rebuild Count
 performance view の rebuild

    stats で確認
 要素の数と同じ回数 rebuild されている 

  24. パフォーマンスの計測と分析 
 Repaint の範囲を抑える 
 04
 ・RepaintBoundary  子ウィジェットの描画を他の部分から分離し、特定の部分だけを Repaint させる


    
  同じ Layer を共有する RenderObject は markNeedPaint にて 
 repaint が必要だと判断されるたびに repaint が発生する
 
  同じ Layer を共有する RenderObject : 祖先にある要素, 子の要素どちらも含む

  25. パフォーマンスの計測と分析 
 RepaintBoundary
 04
 親 Transform.rotate ListView repaint が発生
 祖先へ

    repaintが波及
 RepaintBoundary なしの場合
 子 repaint 範囲が広がる

  26. パフォーマンスの計測と分析 
 RepaintBoundary
 04
 親 子 Transform.rotate ListView repaint が発生


    RepaintBoundary ありの場合
 repaint が祖先まで 
 波及しないようになる 

  27. パフォーマンスの計測と分析 
 RepaintBoundary の付与基準 
 04
 Q: metrics の数値が高ければどこにでも付与すれば良いのか?
 RepaintBoundary

    has the further side-effect of possibly hinting to the engine that it should further optimize animation performance.
 Flutter Engine (GPU) に副作用をもたらす可能性 
 (GPU 内のメモリコストを逼迫させるため) 

  28. パフォーマンスの計測と分析 
 RepaintBoundary の付与基準 
 04
 ・Component 化
 ・Builder 系


     AnimatedBuilder, HookBuilder
 
 解決できない場合のみ付与 
 
 ・Rive 等の animation framework
 ・コンポーネント内に
 複数のアニメーションが存在している 
 A : 段階的に付与するか判断する