WWDC Quick Look 💓 By SwiftGGTeam
Reduce network delays for your app

Reduce network delays for your app

元の動画を見る

ハイライト

Apple は、iOS 15 および macOS Monterey でネットワーク応答性テスト、HTTP/3、TCP Fast Open、Multipath TCP、およびバックグラウンド サービス タイプを提供しており、開発者はネットワークの往復回数とユーザーの待ち時間を削減できます。

主要内容

天気予報アプリを開くと、読み込み中インジケーターが表示されます。コードは高速で、インターフェイスは大きくありません。ユーザーはまだ 1 ~ 2 秒待つ必要があります。

開発者は多くの場合、最初に帯域幅を検討します。ホーム ネットワークは数メガビットからギガビットにアップグレードされましたが、ビデオ会議と Web ページの読み込みは依然として停止しています。 Stuart Cheshire 氏は冒頭でその理由を述べました。アイドル状態の ping 時間は実際の使用体験を表していないからです。ネットワークの使用中はバッファがキューに入れられ、20 ミリ秒のアイドル往復遅延が 600 ミリ秒になる可能性があります。

この種の問題はバッファー肥大化と呼ばれます。パケットはそれ以上早く到着するわけではなく、ネットワーク デバイス上の大きなバッファのキューに入れられるだけです。帯域幅を改善しても、待ち時間をなくすことはできません。

Apple のアプローチは 2 層構造になっています。

最初のレベルは測定です。 iOS 15 の開発者設定に応答性テストが追加され、macOS で利用可能にnetworkQuality注文。動作条件下での応答性を測定し、RPM (往復数/分) で表します。数値が大きいほど、ネットワークはラウンドトリップをより速く完了できます。

2 番目のレベルは、往復の削減です。アプリは光の速度を変更したり、ユーザーの家のルーターを制御したりすることはできません。ただし、アプリケーションは、接続を確立して最初のバイトを取得するために必要なネットワークの往復回数を減らすことができます。このセッションでは、HTTP/3 と QUIC、TCP Fast Open、TLS 1.3、マルチパス TCP、および緊急でないトラフィックをバックグラウンドとしてマークする方法に焦点を当てました。

最初のバイトを待って最適化を開始します

アプリケーションが現在 TCP + TLS 1.2 を使用している場合、ユーザーが最初のバイトを取得するまでにネットワークを 4 往復する必要がある可能性があります。往復遅延が 600 ミリ秒に増加すると、最初のバイトの待機時間は 2.4 秒に近づきます。

HTTP/3、QUIC、TLS 1.3、および TCP Fast Open の値は次のとおりです。これらはハンドシェイク フェーズ中のラウンドトリップを削減します。すでに使用されているものについてはURLSessionアプリの場合、iOS 15 と macOS Monterey ではデフォルトで HTTP/3 が有効になります。サーバーがサポートすると、クライアントは自動的に恩恵を受けることができます。

ネットワークの切り替えによっても待機が発生します

ユーザーが Wi-Fi から屋外に移動すると、デバイスはセルラー ネットワークに切り替わります。通常の TCP 接続を再確立する必要があります。マルチパス TCP を使用すると、TCP 接続がネットワーク スイッチに耐えることができ、システムがより高速なパスを自動的に選択できるようになります。

これは、チャット、ビデオ会議、リモート コントロールなどの対話型アプリケーションでは簡単です。ユーザーが移動しても、接続を最初から開始する必要はありません。

バックグラウンド ダウンロードでフロントエンド リクエストがブロックされるべきではありません

多くのアプリケーションは、画像、音声、またはファイルをプリフェッチします。プリフェッチ自体は合理的ですが、ネットワーク キューがいっぱいになると、ユーザーがプロファイルをクリックしたときに、本当にすぐに表示する必要があるデータがキューの最後に入れられてしまいます。

iOS 15 と macOS Monterey では、バックグラウンド サービス タイプの輻輳制御が改善されています。開発者がプリフェッチ、バッチ同期、および非緊急タスクをバックグラウンドとしてマークすると、システムはバックグラウンド転送を元の完了時間に近づけながら、フォアグラウンド トラフィックを最初に通過させることができます。

詳細

動作条件下でのネットワークの応答性を測定する

(00:36) iOS 15 の開発者設定では、新しい応答性テストがネットワーク領域に追加されます。ネットワーク トラフィックを生成し、動作条件下での応答性を測定します。 macOS 上の対応するコマンド ライン ツールは次のように呼ばれます。networkQuality

networkQuality

キーポイント:

  • networkQualitymacOS でネットワーク応答性テストを実行します。
  • このテストは、アイドル状態の ping ではなく、作業モードでのラウンドトリップ機能に焦点を当てています。
  • 結果は RPM で表され、RPM が高いほどネットワークの応答が速くなります。
  • このインジケーターは、「ネットワーク速度は非常に速いのに、アプリケーションが非常に遅い」というユーザーの不満のシナリオを再現するのに適しています。

(02:13) セッションには特定の数値が示されます。アイドル状態の往復時間は 20 ミリ秒である可能性があり、作業モードでは 600 ミリ秒以上に上昇する可能性があります。アプリケーションの待機時間は、往復にかかる時間と、アプリケーションに必要な往復回数の 2 つの要素によって決まります。

wait time = round-trip time × number of round trips

キーポイント:

  • round-trip time単一ネットワークの往復時間です。
  • number of round tripsこれは、アプリケーション プロトコルが操作を完了するために必要な往復回数です。
  • 開発者がユーザー ネットワークの基礎となる RTT を制御することは困難です。
  • 開発者は、プロトコルと API を介した往復回数を減らすことを選択できます。

HTTP/3 と QUIC: デフォルトでの URLSession の利点

(08:15) iOS 15 と macOS Monterey では、デフォルトで HTTP/3 と QUIC が有効になります。 QUIC は、TCP + TLS よりも高速に接続を確立し、行頭ブロッキング (同じ接続内でのパケット損失により他のデータが待機すること) を軽減するトランスポート プロトコルです。

let session = URLSession.shared
let (data, response) = try await session.data(from: url)

キーポイント:

  • URLSession.sharedシステムが提供する URLSession 構成を使用します。
  • session.data(from:)HTTP リクエストを作成します。
  • 明示的なセッション: アプリケーションがすでに URLSession を使用している場合は、HTTP/3 を使用する準備ができています。
  • HTTP/3 を使用するかどうかには、引き続きサーバー側のサポートが必要です。

(08:47) アプリケーションが独自のアプリケーション層プロトコルを実装している場合、ネットワーク フレームワークの QUIC サポートを使用できます。 QUICパラメータの作成方法を解説します。NWConnection、TLS アプリケーション層プロトコル ネゴシエーション (ALPN、アプリケーション層プロトコル ネゴシエーション) を設定します。

let connection = NWConnection(
    host: "example.com",
    port: 443,
    using: .quic(alpn: ["myproto"])
)

connection.start(queue: myQueue)

キーポイント:

  • NWConnectionネットワーク フレームワーク接続を表します。
  • hostそしてportサーバーをポイントします。
  • .quic(alpn: ["myproto"])QUIC パラメータを使用し、ALPN 経由でアプリケーション プロトコルを宣言します。
  • start(queue:)接続を開始します。
  • サーバーは、対応する QUIC プロトコルと ALPN もサポートしている必要があります。

TCP 高速オープン: 最初のデータをハンドシェイクに入れる

(09:28) TCP は依然として一部のアプリケーションに適しています。 TCP を使用する場合、TCP Fast Open はアプリケーションの最初のデータを TCP ハンドシェイクとともに送信できるため、完全な往復が不要になります。

/* Allow fast open on the connection parameters */
parameters.allowFastOpen = true

let connection = NWConnection(to: endpoint, using: parameters)

/* Call send with idempotent initial data before starting the connection */
connection.send(content: initialData, completion: .idempotent)
connection.start(queue: myQueue)

キーポイント:

  • parameters.allowFastOpen = trueこの接続で TCP Fast Open の使用を許可します。
  • NWConnection(to:using:)これらのパラメータを使用して接続を作成します。
  • connection.send(content:completion:)存在するstart初めてデータを提出する前に。
  • .idempotentこの最初のデータ部分がべき等であり、安全に再生できることを宣言します。
  • connection.start(queue:)接続が開始されると、システムはハンドシェイクとともに最初のデータを送信できます。

(10:14) べき等性が重要な制限です。 HTTP GET リクエストは通常​​、再生できます。携帯電話の購入などの取引リクエストをハンドシェイクで送信することはできません。ネットワークは初めてデータを再送信する可能性があり、非冪等操作により繰り返し実行が発生する可能性があります。

GET / HTTP/1.1
Host: developer.apple.com

キーポイント:

  • GETリソースのリクエスト。
  • Host対象ホストを指定します。
  • プレゼンテーションへのアクセスdeveloper.apple.comGET 記述は冪等リクエストです。
  • TCP Fast Open の最初のデータを配置するのは、リクエストのリプレイによって追加の効果が発生しないことが確認されている場合にのみ適しています。

(11:01) アプリケーションがソケットに基づいている場合は、次のように呼び出すことができます。connectx対応するフラグを使用します。

connectx(fd, ..., CONNECT_DATA_IDEMPOTENT | CONNECT_RESUME_ON_READ_WRITE, ...); // delay SYN
write(fd, ...); // SYN goes out with first data segment

キーポイント:

  • connectxソケット接続を開始します。
  • CONNECT_DATA_IDEMPOTENT初めてのデータを安全に再生できることを宣言します。
  • CONNECT_RESUME_ON_READ_WRITE読み取りおよび書き込み中は接続を継続します。
  • write初めてデータを書き込みます。
  • SYN が最初のデータ セグメントとともに送信されることを示すコメント。

TLS 1.3: デフォルトでハンドシェイクのラウンドトリップが 1 回減少

(12:46) TLS 1.3 では、TLS 1.2 と比較して完全なハンドシェイクの往復がなくなり、より強力なセキュリティが提供されます。セッションの説明 iOS 13.4 以降、URLSession および NWConnection にデフォルトで使用されています。

let session = URLSession.shared
let connection = NWConnection(to: endpoint, using: .tls)

キーポイント:

  • URLSession.sharedシステム TLS スタックを使用します。
  • NWConnection(to:using: .tls)TLS接続を作成します。
  • TLS 1.3 はデフォルトで有効になっており、URLSession または NWConnection に追加のスイッチは必要ありません。
  • TLS 1.3 は初期データを定義しており、これにより冪等リクエストを TLS ハンドシェイクとともに送信できるようになり、ラウンドトリップが節約されます。

マルチパス TCP: ネットワークを切り替えるときに接続を維持します

(13:35) マルチパス TCP を使用すると、デバイスがあるネットワークから別のネットワークに切り替わっても TCP 接続を維持できます。低遅延シナリオで対話モードを使用すると、システムはデータ パケットのより高速なパスを自動的に選択します。

// Multipath TCP
// Save multiple round-trips when switching networks

// On URLSessionConfiguration
let configuration = URLSessionConfiguration.default
configuration.multipathServiceType = .interactive

// On NWParameters
let parameters = NWParameters.tcp
parameters.multipathServiceType = .interactive

キーポイント:

  • URLSessionConfiguration.defaultデフォルトの URLSession 構成を作成します。
  • configuration.multipathServiceType = .interactiveURLSession に対して対話型マルチパス TCP を有効にします。
  • NWParameters.tcpTCPパラメータを作成します。
  • parameters.multipathServiceType = .interactiveNWConnection に対して対話型マルチパス TCP を有効にします。
  • .interactive低遅延トラフィックに適しており、システムはパスの選択を処理します。

緊急でないトラフィックをバックグラウンドとしてマークする

(17:43) アプリケーションには、ユーザーが待機しているフォアグラウンド リクエストと、プリフェッチ、バッチ同期、ログのアップロードなどの緊急ではないリクエストという 2 種類のトラフィックが同時に存在することがよくあります。緊急でないリクエストがボトルネック キューを埋めると、ユーザーがクリックした後に行われたリクエストは後ろのキューに入れられます。

(20:09) フォアグラウンド アプリケーションは、ユーザーが開始しない転送を実行するときにデフォルトの URLSession を引き続き使用できますが、URLRequestバックグラウンドサービスタイプをオンに設定します。ネットワーク フレームワークの対応する設定は次のとおりです。NWParameters.serviceClass

//Use default  URLSession, set background on URLRequest
var request = URLRequest(url: myurl)
request.networkServiceType = .background

//Set service class on parameters to apply to the  NWConnection
let parameters = NWParameters.tls
parameters.serviceClass = .background

キーポイント:

  • URLRequest(url:)リクエストを作成します。
  • request.networkServiceType = .backgroundこの転送がバックグラウンドで行われたものであることを示します。
  • NWParameters.tlsTLS 接続パラメータを作成します。
  • parameters.serviceClass = .backgroundバックグラウンドサービスクラスをNWConnectionに適用します。
  • したがって、システムはネットワーク キューを短く保ち、フォアグラウンド データをより速く配信できるようにします。

(20:37) アプリが長時間の転送を開始し、アプリがハングした後も実行を継続したい場合は、バックグラウンド URLSession を使用する必要があります。時間に左右されないタスクは、isDiscretionaryに設定true、システムがより適切な条件になるまで待機させます。

//Configure background URL Session

lazy var urlSession: URLSession = {
    let configuration = URLSessionConfiguration.background(withIdentifier: "MySession")
    configuration.isDiscretionary = true
    return URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
}()

キーポイント:

  • URLSessionConfiguration.background(withIdentifier:)バックグラウンドセッション構成を作成します。
  • "MySession"バックグラウンドセッション識別子です。
  • configuration.isDiscretionary = trueシステムが転送を実行する適切な時間を選択できるようにします。
  • URLSession(configuration:delegate:delegateQueue:)この構成でセッションを作成します。
  • このモードは、時間に依存しないダウンロード、アップロード、同期タスクに適しています。

サーバーは送信側のキューも減らす必要があります。

(21:17) 送信デバイス自体でも遅延が発生する可能性があります。従来のネットワーク スタックでは非常に大きな送信バッファが使用されており、パケットはネットワークに入る前に数秒間キューに入れられる可能性がありました。 Apple は 2015 年に URLSession と NWConnection に関してこの問題を修正しました。

setsockopt(fd, IPPROTO_TCP, TCP_NOTSENT_LOWAT, &value, sizeof(value));

キーポイント:

  • setsockoptソケットのオプションを設定します。
  • IPPROTO_TCPTCP レベルのオプションの設定を示します。
  • TCP_NOTSENT_LOWAT講演の中で言及された、TCP 非送信低水準点ソケット オプションです。
  • このオプションは、送信側のネットワークにまだ入っていないデータのキューを減らすために使用されます。
  • セッション サーバーがこのオプションを使用しているかどうかをサーバーの運用保守担当者に確認することをお勧めします。

重要ポイント

  1. 対処方法: アプリに「ネットワーク エクスペリエンス診断」ページを追加して、スタック時にシステム ネットワーク応答性テストを実行するようユーザーに促します。 実行する価値がある理由: セッションでは、アイドル状態の ping と動作状態の応答性が明確に区別され、RPM は実際のエクスペリエンスに近くなります。 開始方法: iOS 開発者設定および macOS での応答性テストについて説明するヘルプ ページnetworkQualityユーザーのフィードバックを「ネットワーク速度が遅い」から記録可能な RPM データに変更するコマンド。

  2. 対処方法: スクロールせずに見えるインターフェイスに対して TCP Fast Open を有効にします。 実行する価値がある理由: 通常、スクロールせずに見えるインターフェイスによって、ユーザーに読み込みインジケーターがいつ表示されるかが決まります。 Fast Open では、冪等の最初のリクエストをハンドシェイクに含めることができます。 開始方法: ネットワーク フレームワークの接続パラメータを設定しますparameters.allowFastOpen = true、そしてconnection.start(queue:)前に使用する.idempotent読み取り専用のリクエスト データを送信します。

  3. 対処方法: ネットワーク切り替えをサポートするには、チャット、通話、またはコラボレーション接続を有効にします。 価値がある理由: 接続を再確立すると、ユーザーが Wi-Fi と携帯電話の間を移動する際に複数回の往復が発生します。マルチパス TCP は接続を維持できます。 開始方法: URLSession のセットアップconfiguration.multipathServiceType = .interactive、またはネットワーク フレームワークを設定しますparameters.multipathServiceType = .interactive

  4. 対処方法: イメージのプリフェッチ、オフライン パッケージのダウンロード、およびログのアップロードをバックグラウンド トラフィックとしてマークします。 実行する価値がある理由: 緊急でないトラフィックでキューがいっぱいになると、ユーザーがトリガーしたばかりのフォアグラウンド リクエストの速度が低下します。バックグラウンド サービス タイプを使用すると、システムがキューの長さを制御できます。 始め方:シングルの場合URLRequest設定request.networkServiceType = .background;時間に左右されない長時間のタスクに使用されますURLSessionConfiguration.backgroundそしてセットisDiscretionary = true

  5. やるべきこと: 一連のネットワーク遅延回帰テストを作成します。 価値がある理由: 開発マシン上の 5G、LTE、または高速 Wi-Fi は問題を隠してしまう可能性があるため、Session はネットワーク リンク コンディショナーを使用して実際のネットワーク状態を再現することを推奨しています。 開始方法: iOS 開発者設定でネットワーク リンク コンディショナーを開き、macOS の Apple Developer Web サイトからツールをダウンロードし、高 RTT、パケット損失、および輻輳構成でファースト スクリーン、ログイン、検索、およびアップロード パスをテストします。

関連セッション

コメント

GitHub Issues · utterances