ストリーミングはほとんどのブラウザと
Developerアプリで視聴できます。
-
UIアニメーションの滞りおよびレンダーループに対する検討
Appにおけるスクローリングとアニメーションの滞りを特定し、UIのパフォーマンスを向上させる方法を探ります。 どのようにレンダーループで滞りが発生するか、滞りの時間比を測定する方法、Appを使用する人に最も影響を与える問題を修正する方法を説明します。
リソース
関連ビデオ
WWDC23
WWDC21
Tech Talks
-
ダウンロード
パフォーマンスチームのパトリックです 今日はAppのスクローリングと animation hitchについてお話し― Render Loopを詳しく見ます パフォーマンスエンジニア パトリック・メトカーフ まずhitchとは何か? それからRender Loopと 起こり得る様々なhitchについてお話します 最後にhitchの数値化をお話します ではまずhitchとは何か? Appで画面を指でスクロールして ボタンを押す時― フィードバックや 階層内でのビュー間の遷移が求められます これらのアニメーションは 人とコンテンツを視覚的につなげてくれます
hitchによって アニメーションに飛びが発生すれば― 喜びより混乱を生みます
hitchとは フレームが予定より遅く表示されることを言います collection viewを スクロールする例を見ましょう これはレシピを提案する食事計画Appです ユーザーが画面を指で上にドラッグすると ビュー上のコンテンツが上に移動します でもスクロール中 コンテンツが飛ぶことがありました フレームごとに見ていくと― 最初の3フレームは 指に合わせてコンテンツが動いていますが 次のフレームで コンテンツが止まって見えます 3フレーム目が次のフレームまで残り リピートしたのです 4フレーム目が現れると― 指のところまで飛んだように見えるのです 4フレーム目が遅れて到着したため リピートが発生し― ユーザーはhitchを目にします hitchはRender Loopが 時間どおりに終わらなかった時に発生します Render Loopを説明しましょう Render Loopとはタッチイベントが Appに渡され UIの変更がOSに送られ― フレームが終了する一連のプロセスを言います ループであり デバイスのリフレッシュレートで起きます iPhoneとiPadでは毎秒60フレーム 新しいフレームが16.67ミリ秒ごとに表示されます iPad Proでは毎秒120フレーム 新しいフレームが8.33ミリ秒ごとこに表示されます フレームの始まりに ハードウェアが VSYNCというイベントを発生させます VSYNCは 次のフレームまでの時間を示します デッドラインが見やすいよう display trackでハイライトします VSYNCに合わせて― Render Loopは 時間内にフレームを用意せねばなりません
3段階に分かれます 1段階目はApp内です イベントに対処し UIに変更が加えられます 次の段階に行くには この作業が 次のVSYNCまでに完了しなければなりません 次の段階は render serverという別プロセスで行われます ここでUIが実際にレンダーされます 3段階目に進み フレームが表示されるには― この段階も 次のVSYNCまでに完了しなければなりません
3段階プロセスの注意点は― 表示前に2フレームのプロセスがあることです これをダブルバッファリングと呼びますが もう1つモードがあります hitchを避けるため トリプルバッファリングに変わることもあります render serverに 1フレーム余分に時間が与えられます これはフォールバックモードなので 今はダブルバッファリングについて話しましょう
Render Loopは全部で5フェーズから成ります ループの始まりはイベントフェーズです ここでAppはタッチイベントに対処し UIに変更が必要か判断します 次がコミットフェーズ コミットフェーズでは― AppがUIを更新し それをrender serverに送信します 次のVSYNCで render serverがそれを受け取り― レンダー準備フェーズでGPUに描く準備をします レンダー実行フェーズでは GPUがUIを最終的な画像に描き上げ― 次のVSYNCで フレームが表示されるようにします
毎フレーム スムーズな体験にするには どの段階も重要です レンダー作業もです 別プロセスですが 皆さんのAppの代理で行われるので 時間内にレイヤーツリーを処理し 描けるかどうかは皆さん次第です 例を使ってより詳しく説明しましょう
この例では このフレームをRender Loopの中で追いながら 各フェーズを見ていきます まずはイベントフェーズ Appがイベントを受け取ります イベントとは タッチやネットワークコールバック キーボード入力やタイマーなどです Appはこれらのイベントに反応し― レイヤー階層を変更します 例えばバックグラウンドの色を変えたり レイヤーサイズや位置を変えます
Appがレイヤーの境界を更新すると― Core AnimationがsetNeedsLayoutを呼びます これにより全レイヤーが識別され それらのレイアウトの再計算が必要になります システムが need layoutリクエストをまとめて― 同じ作業を減らすため コミットフェーズに順番どおりに実行します
レイアウトが要るなら― イベントフェーズが終わり次第 コミットフェーズが自動的に始まります まずシステムが レイアウトが必要なレイヤーを取り出し― 親から子までひとつずつ並べていきます レイアウトはよくあるボトルネックです この作業をするのに 数ミリ秒しか時間がないことをお忘れなく viewによってはカスタム描画が必要です ラベル イメージビュー drawRectをオーバーライドするビューなど ビューにビジュアルアップデートが必要なら setNeedsDisplayを呼び出してください レイアウト同様 システムはレイアウトが完成したら― これらのリクエストをまとめます
描画プロセスの間は カスタム描画レイヤーはテクスチャや― グラフィックスコンテキストを受け取り 描き込みます Core Animationに関して言えば これらのレイヤーはまだ ただの画像です 各レイヤーが配置され描かれると― 変更されたレイヤーツリー全体が集められ レンダリングのためrender serverに送られます レンダー準備フェーズ 次はrender server ここでレイヤーツリーを 実際に表示可能な画像にします 準備フェーズでは render serverがAppのレイヤーツリー間を反復し GPUが実行できる リニアなパイプラインを準備します
最上層から始まり 親から子 兄弟から兄弟へと進めていくため レイヤーは後ろから前へ並べられます
次にこのリニアパイプラインはGPUに渡され 各レイヤーが最終テクスチャへと合成されます レイヤーによっては時間がかかります これもよくあるボトルネックの1つで 後述します さて GPUが右の画像をレンダーすると― 次のVSYNCで表示可能になります
Render Loopの各フェーズは パフォーマンスセンシティブでデッドラインがあります デッドラインは次のVSYNCです フレームレートと 低入力レイテンシーを維持するため― このプロセスは どのフレームも並行して実行されています これにより パイプラインが並列になり― システムがレンダーしているうちに Appが新しいフレームを用意できます だからデッドラインが重要になります
Render Loopの仕組みが分かったところで Appによくあるhitchのタイプを見ていきましょう 主要タイプは2つ App内のプロセスで起きるcommit hitch render serverで起きるrender hitch
commit hitchはAppが イベントや コミットの処理に時間がかかりすぎた時に起きます ここではコミットが遅れて デッドラインを超えたため― 次のVSYNCで render serverが処理するものがありません 処理開始まで次のVSYNCを待つしかなく― フレーム表示が1フレーム遅れてしまいます iPhoneやiPadでは16.67ミリ秒になります この遅延をhitch timeと呼び 単位はミリ秒です
コミット作業がさらに1フレーム長くかかれば 2フレーム遅れとなり33.34ミリ秒遅れます 33.34ミリ秒間 スムーズなスクロールでなくなるということです commit hitchの詳細と修正方法は― "Find and Fix Hitches in the Commit Phase"をご覧ください 2つ目のタイプはrender hitchです render serverがレイヤーツリーを時間内に 実行 あるいは用意できない場合に起きます ここでは実行に時間がかかり― VSYNC境界を越えてしまいます フレームが時間内に用意できず― グリーンフレームが 予定より1フレーム遅れて表示されます これも16ミリ秒のhitch timeになります render hitchの詳細や レイヤーツリーを最適化する方法は― "Demystify and Eliminate Hitches in the Render Phase"をご覧ください
さて 以上がhitchの主要タイプです 続いてはhitchを測り定量化する方法を 見ていきましょう
先ほどはhitch timeについて説明しました 単独のhitchを見る場合は役に立ちますが スクロールやアニメーションや遷移などの 長期イベントの場合は役立ちにくい時があります まずスクロールやアニメーションにかかる 時間が同じでないと― 比較が難しくなります フレーム数が同じでなくてはなりません しかもiOSデバイスは 新しいフレームが送信されない場合― 画面が常に更新されるとは限りません テストやデバイス間で hitch timeを比較することが難しいのです そこでhitch time ratioと呼ぶ単位を使います hitch time ratioはインターバル内の 総hitch timeをその時間で割ったものです 合計時間で正規化し エクスペリエンスをまたぎ比較可能にします 単位はhitchミリ秒/秒 1秒あたり 何ミリ秒デバイスがhitchしたかを表します この単位を使って Appのパフォーマンスを測る方法は― "What's New in MetricKit"をご覧ください テストスイートで hitch time ratioを追跡する方法は― "Eliminate Animation Hitches with ZCTest"をご覧ください
最後にhitch time ratioが役立つ例を 見てみましょう こちらは30フレーム iPhoneでは0.5秒分の作業です 各フレームでデッドラインは守られており hitchはありません hitch timeはゼロ hitch time ratioもゼロです
次にこちらは バラバラなインターバルが見られます 表示が長いフレームがあり― コミットやレンダーでhitchが発生しています hitch timeを全部足すと100.02ミリ秒です この0.5秒間で― hitch time ratioは200.04ミリ秒/秒です これは1つの例です 我々Appleが推奨し ツールで使用しているhitch time ratioは― こちらです 目標値はゼロですが 5以下は良好とし ユーザーもほぼ気づくことはありません 5から10の間だと― ユーザーも遅延に気づくため調査が必要です 10以上になると hitchがユーザーに大きく影響するため すぐに調査し Render Loopを最適化すべきでしょう
今日は Render Loopと 新しいフレームが表示される仕組みについて hitchとは何か? commitとrender hitchの2タイプについて 最後にhitch time ratioと― ユーザーが感じる hitchの測り方について話しました
hitchのタイプや修正に関する詳細は― commit hitchとrender hitchに関する 上記2つのセッションをご覧ください 皆さんのスムーズなAppを楽しみにしています ご視聴ありがとうございました
-
-
特定のトピックをお探しの場合は、上にトピックを入力すると、関連するトピックにすばやく移動できます。
クエリの送信中にエラーが発生しました。インターネット接続を確認して、もう一度お試しください。