WWDC Quick Look 💓 By SwiftGGTeam
Ultimate application performance survival guide

Ultimate application performance survival guide

元の動画を見る

ハイライト

Apple は、Xcode Organizer、MetricKit、Instruments、XCTest、および App Store Connect API を使用して、バッテリー、起動、フリーズ、メモリ、ディスク書き込み、スクロール、終了速度などのパフォーマンス指標を関連付け、開発者が開発、テスト、オンライン リリース後にパフォーマンスの低下を継続的に発見できるようにします。

主要内容

パフォーマンスの問題は最初にユーザーの手元に現れます。

MealPlanner にレシピと写真を保存する機能が追加されてから、問題が発生し始めました。リストのスクロールがぎくしゃくしたり、起動時に最初のフレームが長時間表示されなかったり、一度にデータを保存するのに書き込まれるファイルが多すぎる可能性があります。開発者はデスクトップ上でそれを再現できないかもしれませんが、ユーザーは実際のデバイスでこれらの問題に遭遇しています。

以前は、この種の問題に対処する一般的なアプローチは、ユーザーからのフィードバックを待ってから原因を推測しようとすることでした。バッテリー、起動、遅延、メモリ、ディスク書き込みのためのツールがあります。データが分散しており、トラブルシューティングの道のりは非常に長くなります。新しいバージョンのリリース後、特定の指標が悪化した場合、開発者はまずどこが悪化したかを把握し、次に対応するコードを見つける必要があります。

Apple はこのセッションで完全なパスを提供します。 Xcode Debug navigator と Instruments を使用して、開発中のシーンを観察します。テスト中に XCTest を使用してパフォーマンス テストを作成します。 Xcode Organizer、MetricKit、App Store Connect API をオンラインで使用して、実際のデバイス上で集約されたデータを読み取ります。

この方法は、パフォーマンスの最適化は感覚だけに頼ることができないという同じ問題点を解決します。すべての質問にはインジケーターが必要であり、各インジケーターはユーザーのアクションまたはコード部分に戻ることができなければなりません。

8 つのインジケーターは 5 つのツールセットに対応します

講演ではまず、バッテリー使用量、起動時間、ハング率、メモリ、ディスク書き込み、スクロール、終了、MXSignposts の 8 つの主要な指標を挙げています (01:54)。これらのインジケーターは、電力消費、起動の遅さ、インターフェイスの無反応、スクロールのスタック、システムによる強制終了など、ユーザーが最も認識しやすいエクスペリエンスをカバーします。

ツールも階層化されています。 Xcode Organizer はオンライン バージョンの傾向を調べ、MetricKit はデバイス側のテレメトリを収集し、Instruments は開発マシン上のコール スタックを特定し、XCTest はパフォーマンス要件をテストに書き込み、App Store Connect API を使用してチームが同じデータを独自の分析システムに接続できるようにします。

詳細

MetricKit を使用してオンライン テレメトリを収集する

(05:46) MetricKit は、デバイス側のパフォーマンス テレメトリ フレームワークです。アプリは登録のみが必要ですMXMetricManagerSubscriber、毎日のメトリクスと診断ペイロードを受信します。講演では、バッテリーログやCPUインジケーターなどのデータをアプリ独自のコンテキストと組み合わせることで、オンライン問題の根本原因を絞り込むことができると述べた。

import MetricKit

class AppMetrics: MXMetricManagerSubscriber {
    init() {
        let shared = MXMetricManager.shared
        shared.add(self)
    }

    deinit {
        let shared = MXMetricManager.shared
        shared.remove(self)
    }

    // Receive daily metrics
    func didReceive(_ payloads: [MXMetricPayload]) {
        // Process metrics
    }

    // Receive diagnostics
    func didReceive(_ payloads: [MXDiagnosticPayload]) {
        // Process metrics
    }
}

キーポイント:

  • import MetricKitMetricKit API の紹介。
  • AppMetrics従うMXMetricManagerSubscriber、このオブジェクトがパフォーマンス データを受信できることを示します。
  • MXMetricManager.sharedグローバル メトリック マネージャーを取得します。
  • shared.add(self)初期化時にサブスクライバを登録します。
  • shared.remove(self)講演では、リリース時にサブスクライバーを削除することが推奨されています。
  • didReceive(_ payloads: [MXMetricPayload])毎日のメトリクス ペイロードを受信します。
  • didReceive(_ payloads: [MXDiagnosticPayload])診断ペイロードを受信します。

(07:00) オンライン データの同じバッチも Xcode Organizer に入力されます。開発者は、過去 16 のアプリ バージョンのバッテリー使用量の傾向を確認したり、Xcode 13 で追加された [回帰] ペインで最新バージョンの大幅に増加したメトリクスを確認したりできます。

XCTest を使用してスクロールラグを測定する

(10:29) スクロールの遅延は、次の画面が更新されるまでに新しいコンテンツの準備ができていないという特定の事実に起因します。ユーザーに見えるのは、フレームをスキップし、ジッタリングし、フリーズするリストです。スピーチ用XCTOSSignpostMetric.scrollDecelerationMetricスタックしたバージョンのリリースを防ぐためにローリング パフォーマンス テストを作成しました。

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)
    }
}

キーポイント:

  • app.launch()UIテスト対象アプリを起動します。
  • app.staticTexts["Meal Planner"].tap()ミールプランナーのページに移動します。
  • app.collectionViews.firstMatchスクロール オブジェクトとして最初のコレクション ビューを見つけます。
  • XCTMeasureOptions()測定オプションを作成します。
  • .manuallyStopステータスをリセットするアクションを除外するために、テストで測定を手動で停止させます。
  • XCTOSSignpostMetric.scrollDecelerationMetric計測ロールの減速位相を指定します。
  • foodCollection.swipeUp(velocity: .fast)テスト中のアクションであるクイック スライド アップを実行します。
  • stopMeasuring()測定をやめてください。
  • foodCollection.swipeDown(velocity: .fast)インターフェイスをスクロールして戻し、次の測定に備えて状態を復元します。

(11:25) iOS 15 および macOS 12 では、MetricKit は問題が発生した直後にハング診断を含む診断を提供します。オンラインの問題は翌日の日次ペイロードを待つ必要がなく、開発者はオンサイト データをより迅速に取得できます。

MXSignpost タグを使用したカスタム アニメーション

(11:53) スクロールに加えて、アプリにはカスタム アニメーションもあります。 MetricKitのiOS 15MXSignpost関連する API は、キー コードの間隔を管理するために使用されます。mxSignpostAnimationIntervalBeginアニメーションの開始をマークし、mxSignpost.end終了をマークした後、MetricKit はこの間隔でヒッチ率テレメトリを収集します。

import MetricKit

func startAnimating() {
    // Mark the beginning of animations
    mxSignpostAnimationIntervalBegin(
        log: MXMetricManager.makeLogHandle(category: "animation_telemetry"),
        name: "custom_animation")
}

func animationDidComplete() {
    // Mark the end of the animation to receive the collected hitch rate telemetry
    mxSignpost(OSSignpostType.end,
        log: MXMetricManager.makeLogHandle(category: "animation_telemetry"),
        name: "custom_animation")
}

キーポイント:

  • MXMetricManager.makeLogHandle(category:)MetricKitが使用するログハンドルを作成します。
  • category: "animation_telemetry"アニメーション テレメトリをグループ化して、その後の分析を容易にします。
  • mxSignpostAnimationIntervalBeginアニメーション間隔の開始をマークします。
  • name: "custom_animation"このアニメーションに名前を付けます。
  • animationDidComplete()アニメーションが完了すると呼び出されます。
  • mxSignpost(OSSignpostType.end, ...)アニメーション間隔の終了を同じ名前でマークします。
  • 同じグループで開始して終了するlogそしてname, MetricKitは間隔を一致させることができます。

XCTest を使用したディスク書き込みの測定

(13:51) ディスクへの書き込みが頻繁に行われると、動作が遅くなり、デバイスの NAND の状態に影響を与える可能性があります。講義では、最初に Instruments のファイル アクティビティ テンプレートを使用してファイル システム コールを表示し、次にXCTStorageMetricクリティカル パスをパフォーマンス テストとして記述します。

// Example performance XCTest

func testSaveMeal() {
    let app = XCUIApplication()
    let options = XCTMeasureOptions()
    options.invocationOptions = [.manuallyStart]

    measure(metrics: [XCTStorageMetric(application: app)], options: options) {
        app.launch()
        startMeasuring()

        let firstCell = app.cells.firstMatch
        firstCell.buttons["Save meal"].firstMatch.tap()

        let savedButton = firstCell.buttons["Saved"].firstMatch
        XCTAssertTrue(savedButton.waitForExistence(timeout: 2))
    }
}

キーポイント:

  • XCUIApplication()UI テストで App オブジェクトを作成します。
  • XCTMeasureOptions()測定構成を作成します。
  • .manuallyStartアプリの起動後にテストの測定を開始します。
  • XCTStorageMetric(application: app)このアプリのディスク書き込みを測定するように指定します。
  • measure(metrics:options:)測定するユーザーアクションをラップします。
  • app.launch()アプリを起動してもまだ測定は始まっていません。
  • startMeasuring()ディスクへの書き込みは、保存アクションの前から記録されます。
  • firstCell.buttons["Save meal"].firstMatch.tap()ユーザーが食事を節約する様子をシミュレートします。
  • XCTAssertTrue(savedButton.waitForExistence(timeout: 2))保存が完了したことを確認します。

(14:16) このテストではベースラインを設定できます。予想される書き込み量を超えると、テストは失敗します。オンライン バージョンがリリースされた後、オーガナイザーのディスク書き込みメトリクスは、古いバージョンと比較した現在のバージョンの傾向を示すことができます。 1 GB/24 時間を超える書き込みでは、スタック トレースを含むディスク書き込みレポートも生成されます。

ツールチェーンを使用して起動、終了、メモリを追跡する

(19:00) 起動時間とは、ユーザーがアイコンをクリックしてからアプリが最初のフレームをレンダリングするまでの時間を指します。アプリ起動テンプレートはアプリを 5 秒間実行し、時間プロファイルとスレッド状態トレースを収集して、開発者が起動中にスレッドがブロックされた理由を確認できるようにします。

func testLaunchPerformance() throws {
    let app = XCUIApplication()

    measure(metrics: [XCTApplicationLaunchMetric()]) {
        app.launch()
    }
}

キーポイント:

  • XCUIApplication()テスト対象のアプリを作成します。
  • measure(metrics:)パフォーマンス測定ブロックを作成します。
  • XCTApplicationLaunchMetric()測定された起動パフォーマンスを指定します。
  • app.launch()これはテスト中のアクションであり、ユーザーがアイコンをクリックした後の起動プロセスに対応します。

(21:19) メモリは、アプリ、システム、カーネルによって共有されるリソースです。アプリがメモリ制限を超えると、システムによって終了されます。次回ユーザーが開くときは、完全な起動プロセスのみを実行できます。講演では、Instruments の Leaks、Allocations、VM Tracker テンプレートを使用してメモリを分析することが提案されています。 MXSignpost を使用してキー コード セグメントをラップし、より詳細なメモリ テレメトリを収集することもできます。

import MetricKit

// Collect memory telemetry

func saveAppAssets() {
    mxSignpost(OSSignpostType.begin,
        log: MXMetricManager.makeLogHandle(category: "memory_telemetry"),
        name: "custom_memory")

    // save app metadata

    mxSignpost(OSSignpostType.end,
        log: MXMetricManager.makeLogHandle(category: "memory_telemetry"),
        name: "custom_memory")
}

キーポイント:

  • mxSignpost(OSSignpostType.begin, ...)重要なコードセクションの先頭にマークを付けます。
  • category: "memory_telemetry"このテレメトリをメモリ分析カテゴリに入れます。
  • name: "custom_memory"間隔に名前を付けます。
  • // save app metadata実際に観察する必要があるリソース節約ロジックを表します。
  • mxSignpost(OSSignpostType.end, ...)間隔の終わりを示します。
  • MetricKit がこのセクションのメモリ データを要約しやすくするために、開始と終了に同じカテゴリと名前を使用します。

重要ポイント

  1. やるべきこと: アプリのパフォーマンス状態ページを作成し、最新バージョンのバッテリー、起動、遅延、ディスク書き込みの傾向のみを表示します。 実行する価値がある理由: Xcode Organizer と App Store Connect API はすでにオンライン集計データを提供しているため、チームはパフォーマンスの回帰を毎日の目に見える指標に変えることができます。 開始方法: まず、オーガナイザーでバッテリー使用量、起動時間、ハング レート、ディスク書き込みを手動で確認し、次に App Store Connect API を使用して同様の JSON データを内部ダッシュボードに取り込みます。

  2. やるべきこと: ホームページ リストのスクロール パフォーマンス テストを作成します。 実行する価値がある理由: スクロールのラグはユーザーの滞在時間に直接影響します。XCTOSSignpostMetric.scrollDecelerationMetricリリース前にラグが発生するリスクを防ぐことができます。 開始方法: UI テストを使用して、リスト ページを開きます。measure(metrics:)に実行されましたswipeUp(velocity:)、使用XCTMeasureOptions状態をリセットする手順は除外します。

  3. 対処方法: イメージのインポート、キャッシュの更新、バッチ保存などの負荷の高い I/O 操作に対するディスク書き込みテストを追加します。 実行する価値がある理由: 講演では、ディスクへの書き込みが頻繁に行われるとエクスペリエンスが遅くなる可能性があることが指摘されており、オーガナイザーは 24 時間で 1 GB を超える書き込みが行われた場合にもレポートを生成します。 開始方法: を使用しますXCTStorageMetric(application:)一般的な保存アクションをラップし、ベースラインを設定し、予想される書き込み量を超えるコードがテスト段階で失敗するようにします。

  4. やるべきこと: MXSignpost をカスタム アニメーションとアセットの保存パスに追加します。 実行する価値がある理由: MetricKit はカスタム間隔でヒット率とメモリ テレメトリを収集でき、オンラインの質問をビジネス アクションにマッピングできます。 開始方法: を使用しますMXMetricManager.makeLogHandle(category:)カテゴリを作成し、クリティカル パスの最初と最後で呼び出します。mxSignpostAnimationIntervalBeginまたはmxSignpost

  5. やるべきこと: 起動プロセスのパフォーマンスのベースラインを確立します。 実行する価値がある理由: 起動が遅いとシステムが終了する可能性があり、次回システムを開くときにユーザーは起動プロセス全体を再度実行する必要があります。 開始方法: XCTest で使用するXCTApplicationLaunchMetric()起動を測定し、Instruments の App Launch テンプレートを使用して、起動前の 5 秒間の時間プロファイルとスレッド状態トレースを表示します。

関連セッション

コメント

GitHub Issues · utterances