WWDC Quick Look 💓 By SwiftGGTeam
Eliminate animation hitches with XCTest

Eliminate animation hitches with XCTest

元の動画を見る

ハイライト

Apple を Xcode 12 で実現XCTOSSignpostMetricアニメーションを認識するos_signpostインターバルと UIKit のスクロールとナビゲーションのサブインジケーター、パフォーマンス XCTest は、ヒット数、合計ヒッチ時間、ヒッチ時間比率、フレーム レート、フレーム カウントを収集し、テスト ベースラインを使用してリリース プロセスにアニメーションの回帰が入るのを防ぎます。


主要内容

リストのスクロールとページ遷移は、最も過小評価されているパフォーマンス パスです。この機能は完成したように見えますが、ユーザーがスワイプするとすぐに、リストが指に追従せず、特定のフレームに長時間留まり、次のフレームで突然正しい位置に戻ってしまうことがわかります。セッションでは、ユーザーが感じるこのジッターをヒッチと呼びます。フレームが予想よりも遅れて画面に表示されることです。

1 秒あたりのフレーム数だけを見て判断を誤るのは簡単です。テストにまだ時間が残っている場合、フレーム レートが歪んでしまいます。ゲーム、ビデオ、時計のアイコンも、意図的に画面のリフレッシュ レートよりも低い頻度で更新することを選択する場合があります。したがって、Apple はアニメーションの問題を測定するためにヒッチ時間とヒッチ率を使用することを推奨しています。ヒッチ時間の目標は常に 0 であり、ヒッチ比は、異なる長さのテストの比較を容易にするために、合計ヒッチ時間を 1 秒あたりのミリ秒に正規化します。

Xcode 12 の変更は、このインジケーターのセットを XCTest に取り込むことです。開発者はカスタムアニメーションを使用できるos_signpostアニメーションの間隔マーキングでは、UIKit によってすでにマークされているスクロール間隔とナビゲーション間隔を直接使用することもできます。テストの実行後、レポート UI に新しいアニメーション指標が表示され、現在の平均をベースラインに設定できるようになります。次の変更によりスクロールが遅くなった場合、パフォーマンス XCTest が開発プロセスで最初に公開されます。

セッションのデモンストレーションは非常に具体的です。Meal Planner アプリは、リスト項目に画像を追加する前に、スクロール パフォーマンス テストを使用してベースラインを確立します。テストを再実行すると、ヒット数が増加し、問題はメインスレッドにありました。scaleAspectFit電話。修正方法は、代わりにコア アニメーションを使用することですsetContentMode、画像の再描画を GPU に引き渡し、メインスレッドのワークロードを軽減します。テストを再度実行すると、アニメーション メトリックはゼロ ヒッチに戻りました。

詳細

1. まず比較可能な指標としてヒッチを定義します。

(00:38) ヒッチとは、フレームが予想よりも遅れて表示されることです。iPhone と iPad は通常、60 Hz、フレームあたり約 16.67 ミリ秒で画面を更新します。 iPad Pro は 120Hz、フレームあたり約 8.33ms まで到達できます。フレームが予期された VSYNC に達しない場合は常に、ヒッチが発生します。

(02:10) Apple は 2 つの定量化方法を提供しています。遅延時間は、フレームが画面に到着するまでのミリ秒数です。ヒッチ率は、テスト中の合計ヒッチ時間をテスト期間で割った値 (ミリ秒/秒) です。セッションで示されたエクスペリエンス ラインは、5ms/s 未満は良好なエクスペリエンス、5 ~ 10ms/s は調査が必要、10ms/s 以上は即時に対処する必要がある、というものです。

2. アニメーション サインポストを使用してカスタム アニメーション間隔をマークします。

06:35XCTOSSignpostMetricXcode 11ではすでに測定が可能ですos_signpost間隔の長さ。Xcode 12でアニメーション間隔を追加した後、開始イベントを通常のbeginからanimationBegin、同じタグはアニメーション関連のインジケーターを返すことができます。

os_signpost(.animationBegin, log: logHandle, name: "performAnimationInterval")
os_signpost(.end, log: logHandle, name: "performAnimationInterval")

キーポイント:

  • animationBeginこの間隔が画面アニメーションに対応することを宣言します。
  • end同じ名前で間隔を終了すると、テストではこの間隔内で発生したアニメーションのパフォーマンスのみがカウントされます。
  • Xcode 12 は、持続時間に加えて、ヒット数、合計ヒッチ時間、ヒッチ時間比率、フレーム レート、およびフレーム カウントを返します。

3. UIKit でマークされたスクロール間隔とナビゲーション間隔を直接使用します。

(06:55) 説明する必要のない UIKit シーンがたくさんあります。XCTOSSignpostMetricナビゲーション遷移、スクロール減速、スクロールドラッグなどのサブインジケーターが提供され、アプリ内の最も一般的なインタラクションパスを直接カバーするのに適しています。

extension XCTOSSignpostMetric {
     open class var navigationTransitionMetric: XCTMetric { get }
     open class var customNavigationTransitionMetric: XCTMetric { get }
     open class var scrollDecelerationMetric: XCTMetric { get }
     open class var scrollDraggingMetric: XCTMetric { get }
}

キーポイント:

  • navigationTransitionMetric標準のナビゲーション遷移を測定するために使用されます。
  • customNavigationTransitionMetricカスタム ナビゲーション トランジションをオーバーライドします。
  • scrollDecelerationMetric指を離した後のスクロールの減速フェーズに注意してください。
  • scrollDraggingMetricユーザーのドラッグ中のスクロールのパフォーマンスに注意してください。

4. スクロールパフォーマンスを Performance XCTest として記述します。

(07:12) サンプル テストでは、まずアプリケーションを起動し、食事プランナー ページに入り、最初のコレクション ビューを見つけます。measure(metrics:)一度巻いて素早くスライドさせるとXCTestが集まりますscrollDecelerationMetric対応するアニメーション インジケーター。

// Measure scrolling animation performance using a Performance XCTest
func testScrollingAnimationPerformance() throws {
    app.launch()
    app.staticTexts["Meal Planner"].tap()
    let foodCollection = app.collectionViews.firstMatch

    measure(metrics: [XCTOSSignpostMetric.scrollDecelerationMetric]) {
        foodCollection.swipeUp(velocity: .fast)
    }
}

キーポイント:

  • app.launch()アプリケーションの起動時に各テストが開始されるようにします。
  • app.staticTexts["Meal Planner"].tap()測定するページを入力します。
  • app.collectionViews.firstMatchリストコンテナを見つけます。
  • measure(metrics:)このパフォーマンス テストがスクロール減速インジケーターを収集することを指定します。
  • swipeUp(velocity: .fast)Xcode 12 でサポートされているスクロール速度パラメータを使用して、ジェスチャ入力のランダム性を低減します。

5. 測定終了ごとにアプリケーションステータスをリセットする

08:02measureデフォルトでは 5 回実行されます。上に5回連続でスワイプするだけです。後続のラウンドでは異なる内容が測定される場合があります。例えばXCTMeasureOptions手動停止を有効にし、測定を停止した後にリストを後ろにスライドさせます。

func testScrollingAnimationPerformance() throws {
    app.launch()
    app.staticTexts["Meal Planner"].tap()
    let foodCollection = app.collectionViews.firstMatch

    let measureOptions = XCTMeasureOptions()
    measureOptions.invocationOptions = [.manuallyStop]

    measure(metrics: [XCTOSSignpostMetric.scrollDecelerationMetric],
            options: measureOptions) {
        foodCollection.swipeUp(velocity: .fast)
        stopMeasuring()
        foodCollection.swipeDown(velocity: .fast)
    }
}

キーポイント:

  • XCTMeasureOptions()この測定の実行オプションを作成します。
  • .manuallyStopテスト コードがインジケーター収集をアクティブに終了できるようにします。
  • stopMeasuring()後続の操作はパフォーマンス サンプルに入力されなくなります。
  • swipeDown(velocity: .fast)次のラウンドのためにリストを同等の状態に復元します。

(08:18) テストスキームも結果に影響します。パフォーマンス XCTest 用に別のスキームを確立し、リリース ビルド構成を使用し、デバッガー、自動スクリーンショット、コード カバレッジ、およびランタイム サニタイズ、ランタイム API チェック、およびメモリ管理の診断オプションをオフにすることをお勧めします。

(09:01) レポート UI には、新しいアニメーション指標が表示されます。例 Hitch Time Ratio を選択すると、5 ラウンドの平均は 1.2ms/s になります。開発者はこの平均をベースラインとして設定し、今後のテストでそれと比較することができます。

11:12XCTOSSignpostMetric測定ブロックで出力されるターゲット サインポスト間隔のみをカウントします。測定ブロックは、同じスライド上で同時にモニタリングするなど、複数の異なる間隔をモニタリングすることもできます。scrollDecelerationMetricそしてscrollDraggingMetric

重要ポイント

  • コア リストにスクロール ベースラインを追加: 手順: ホームページ フィード、製品リスト、またはギャラリー用に 1 つを作成します。scrollDecelerationMetricテスト。実行する価値がある理由: このようなページのパフォーマンス低下は通常、画像、影、レイアウト計算、またはデータ バインディングによって発生し、ユーザーが最初に認識するのはスクロールの遅延です。開始方法: 固定の入り口を選択し、ページに入った後に実行しますswipeUp(velocity: .fast)、現在の安定した結果をベースラインに設定します。

  • 遷移アニメーションを UI テストに組み込む: やるべきこと: 主要なページにジャンプを追加するnavigationTransitionMetricまたはcustomNavigationTransitionMetric。実行する価値がある理由: ナビゲーションの遷移はデータの準備とビューの構築の間に挟まれることが多く、メインスレッドへの負荷が目に見える遅れに直接変わります。開始方法: UI テストを使用してタップを 1 回トリガーし、measure(metrics:)遷移アクションをラップします。

  • カスタム アニメーションに標識を追加: 作業内容: 独自に開発したアニメーション、複雑なジェスチャー、またはキャンバス更新コードの周囲にアニメーションを追加します。os_signpost。実行する価値がある理由: UIKit はすでに一般的なスクロールとナビゲーションをカバーしていますが、ビジネス カスタム アニメーションでは測定境界を自分で定義する必要があります。開始方法: 使用するos_signpost(.animationBegin, ...)和同名.endアニメーション間隔をラップしてテストで使用するXCTOSSignpostMetric収集結果。

  • パフォーマンス テスト環境を別途修正します: 対処方法: パフォーマンス XCTest 用の独立したスキームを確立します。実行する価値がある理由: デバッガー、スクリーンショット、カバレッジ、およびランタイム診断はすべて測定結果に干渉し、ベースラインが不安定になります。開始方法: 既存のテスト スキームをコピーし、それを [リリース] に変更し、セッションにリストされているデバッグ オプションと診断オプションをオフにします。

  • 利用可能なテストで新しい画像を保護: 対処方法: 画像、サムネイル、または動的コンテンツをリスト項目に追加する前後に、同じスクロール パフォーマンス テストを実行します。実行する価値がある理由: セッションのデモンストレーションでは、メイン スレッドのイメージ スケーリングがヒッチを直接増加させることが示されています。開始方法: まずゼロ ヒッチまたは低ヒッチ ベースラインを記録し、イメージ関数を組み合わせてインジケーターを比較します。回帰が見つかった場合は、まずメインスレッドでのデコード、スケーリング、描画の動作を確認します。

関連セッション

コメント

GitHub Issues · utterances