ネットワーク アクセスを最適化する

無線通信を使用したデータ転送は、アプリのバッテリーの消耗に大きな影響を及ぼす要因の 1 つです。ネットワーク アクティビティに関連するバッテリーの消耗を最小限に抑えるには、基盤となる無線通信ハードウェアに対して接続モデルがどのような影響を及ぼすかを理解することが重要です。

このセクションでは、無線通信のステートマシンを紹介し、アプリの接続モデルと無線通信のステートマシンの相互作用について説明します。また、アプリのデータ消費がバッテリーに与える影響を最小限に抑えるためのいくつかの手法を紹介します。

無線通信のステートマシン

ユーザーのデバイスの無線通信には、バッテリー消費量を最小限に抑えるための省電力機能が組み込まれています。無線通信は、完全にアクティブな状態では大量の電力を消費しますが、非アクティブな状態やスタンバイ状態ではほとんど電力を消費しません。

重要な点として、無線通信はスタンバイ状態から完全にアクティブな状態に瞬時に移行することはできません。無線通信の「パワーアップ」には遅延期間が伴います。そのため、バッテリーは、無線通信の「パワーアップ」に伴う遅延を最小限に抑えながら、使用していないときに電力を節約するために、高エネルギー状態から低エネルギー状態にゆっくりと移行します。

一般的な 3G ネットワークの無線通信のステートマシンは、以下の 3 つのエネルギー状態で構成されます。

  • 最大電力: 接続がアクティブなときに使用され、デバイスは 最大転送率でデータを転送できます。
  • 低電力: バッテリー消費量を 約 50% 削減する中間状態。
  • スタンバイ: ネットワーク 接続がアクティブでないときの最小電力消費状態。

低電力とスタンバイの状態では電池の消耗がかなり少なくなりますが、ネットワーク リクエストに対する遅延が非常に大きくなります。低電力から最大電力の状態に戻るのには約 1.5 秒かかるのに対し、スタンバイから最大電力の状態に遷移するのには 2 秒以上かかることもあります。

レイテンシを最小限に抑えるには、ステートマシンで低電力のエネルギー状態への遷移を先送りにします。図 1 では、AT&T が測定した一般的な 3G 無線通信のタイミングを使用しています。


図 1.一般的な 3G 無線通信のステートマシン

各デバイスの無線通信ステートマシン(特に、付随する遷移時遅延(「テールタイム」)と起動時遅延)は、使用されている無線通信テクノロジー(3G、LTE、5G など)によって異なり、デバイスが利用している携帯通信会社ネットワークによって定義と設定が行われています。

このページでは、AT&T 提供のデータに基づき、一般的な 3G 無線通信の代表的なステートマシンについて説明します。説明対象は 3G ですが、一般原則やベスト プラクティスは、すべての無線通信実装に当てはまります。

このアプローチは一般的なモバイル ウェブ ブラウジングに特に効果的で、ウェブ ブラウジング中に発生する望ましくない遅延を防ぐことができます。また、テールタイムが比較的短いため、ブラウジング セッションが終了次第、無線通信は低エネルギーの状態に遷移できます。

残念ながらこのアプローチでは、アプリがフォアグラウンド(遅延が目立つ)とバックグラウンド(電池寿命を優先する必要がある)の両方で実行される Android のような最新のスマートフォン向け OS では、アプリの効率が低下する可能性があります。

アプリが無線通信ステートマシンに及ぼす影響

新しいネットワーク接続を確立するたびに、無線通信は最大電力の状態に遷移します。上記の一般的な 3G 無線通信のステートマシンでは、転送中(およびテールタイムの追加の 5 秒)は最大電力の状態が維持され、その後の 12 秒間は低電力の状態になります。このように、一般的な 3G デバイスでは、すべてのデータ転送セッションにおいて少なくとも 18 秒間、無線通信によって電力が消費されます。

実際面では、たとえば、1 分間に 3 回、1 秒間のデータ転送を行うアプリでは、無線通信が絶えずアクティブな状態に維持され、スタンバイの状態になろうとするとすぐに最大電力の状態に戻ります。


図 2.1 分間に 3 回、1 秒間の転送を実行する場合の無線通信の相対的な電力消費量。図には、実行間の「パワーアップ」遅延は含まれていません。

これに対し、同じアプリでデータ転送を一括処理し、1 分間に 1 回、3 秒間の転送を実行する場合、無線通信が最大電力の状態に維持されるのは 1 分間に合計 20 秒間のみになります。これにより、無線通信は 1 分間に 40 秒間スタンバイ状態になるため、バッテリーの消耗を大幅に抑えることができます。


図 3.1 分間に 1 回、3 秒間の転送を実行する場合の無線通信の相対的な電力消費量。

最適化の手法

ネットワーク アクセスがバッテリー寿命に与える影響を理解したところで、バッテリーの消耗を抑えながら、高速でスムーズなユーザー エクスペリエンスを提供するためにできることについて説明します。

データ転送を一括処理する

前のセクションで説明したように、データ転送を一括処理して、転送頻度を減らしながら転送するデータ量を増やすことは、バッテリー効率を向上させる最良の方法の 1 つです。

もちろん、ユーザー アクションに応じてデータを即座に送受信する必要があるアプリでは、必ずしも可能ではありません。この問題は、 データを予測してプリフェッチすることで軽減できます。ログや分析情報をサーバーに送信するなどの緊急性の低いアプリ開始のデータ転送は、バッチ処理や一括処理に非常に適しています。バックグラウンドでのネットワーク転送のスケジュール設定に関するヒントについては、アプリ開始タスクの最適化をご覧ください。

プリフェッチ データ

データをプリフェッチすると、アプリが実行する独立したデータ転送セッションの回数を効果的に減らすことができます。プリフェッチを使用すると、ユーザーがアプリ内でアクションを実行したときに、後続のユーザー アクションに必要となる可能性のあるデータをアプリが予測して、1 回の接続で一括取得するようになります。

転送を前倒しで行うことで、データのダウンロードの際に必要になる無線通信の有効化の回数を減らすことができます。その結果、電池を節約できるだけでなく、遅延の改善、必要な帯域幅の削減、ダウンロード時間の短縮も実現できます。

また、プリフェッチにより、操作を実行したりデータを表示したりする前にダウンロードが完了するのを待機することで生じるアプリ内遅延を最小限に抑え、ユーザー エクスペリエンスを向上させることができます。

実際の例を次に示します。

ニュース リーダー

多くのニュースアプリでは、カテゴリが選択された後にのみヘッドラインをダウンロードし、ユーザーが記事を読む場合にのみ記事全文をダウンロードし、ユーザーがビューにスクロールしたときにのみサムネイルをダウンロードすることによって帯域幅を削減しようとします。

このアプローチでは、ユーザーがヘッドラインをスクロールし、カテゴリを変更して、それから記事を読むと、そのセッションのほとんどの間、無線通信が強制的にアクティブな状態に維持されます。それだけでなく、エネルギー状態の切り替えが絶えず行われるため、カテゴリを変更するときや記事を読むときに大幅な遅延が生じます。

おすすめの方法は、アプリの起動時に適量のデータをプリフェッチする方法です。まず、ニュースのヘッドラインとサムネイルの最初のセットをダウンロードし(これにより、起動時の遅延を軽減できます)、その後で、残りのヘッドラインとサムネイル、および少なくともメインのヘッドライン リストから読むことができる各記事のテキストをダウンロードします。

もう 1 つのおすすめの方法は、すべてのヘッドライン、サムネイル、記事のテキストに加え、できれば記事の画像もすべてプリフェッチしてしまう方法です。これは通常、あらかじめ決められたスケジュールで、バックグラウンドで行います。ただし、この方法には、使用されることのないコンテンツをダウンロードすることで大量の帯域幅とバッテリー寿命を消費するリスクがあるため、慎重に実装する必要があります。

その他の考慮事項

データのプリフェッチには多くのメリットがありますが、プリフェッチを積極的に使用しすぎると、使用しないデータをダウンロードすることで、バッテリーの消耗が激しくなり、帯域幅の使用量(およびダウンロード容量)が増加するリスクが生じます。また、プリフェッチが完了するのをアプリが待機している間、プリフェッチによってアプリの起動が遅れないようにすることも重要です。具体的に言うと、データを着実に処理し、あるいは連続した転送を優先して開始して、アプリの起動に必要なデータを最初にダウンロードして処理するようにします。

どれだけ積極的にデータをプリフェッチするかは、ダウンロードするデータのサイズと、ダウンロードしたデータが使用される可能性によって異なります。上記のステートマシンに基づくおおよその目安として、現在のユーザーセッションで使用される可能性が 50% のデータの場合、通常は、使用しないデータのダウンロードにかかる潜在的なコストがそのデータを最初にダウンロードしないことによる潜在的な節約コストと一致するまでの約 6 秒の間(約 1 ~ 2 メガバイト)、プリフェッチを実行できます。

一般に、2 ~ 5 分ごとに 1 ~ 5 メガバイトのオーダーで新たにダウンロードを開始するだけで済むようにデータをプリフェッチすることをおすすめします。

大規模なダウンロード(動画ファイルなど)の場合、この原則に沿って定期的(2 ~ 5 分ごと)に分割してダウンロードを行うことで、数分以内に再生される可能性のある動画データだけを効果的にプリフェッチするようにしてください。

1 つの解決策として、Wi-Fi に接続している場合、またはデバイスが充電中の場合にのみ、完全なダウンロードを行うようにスケジュール設定する方法があります。WorkManager API はまさにこのユースケースをサポートしており、デバイスが充電中である、Wi-Fi に接続しているなど、デベロッパーが指定した条件を満たすまでバックグラウンド処理を制限できます。

リクエストを行う前に接続を確認する

モバイル デバイスにとって、モバイルデータ信号の検索は極めて消費電力の多い処理の 1 つです。ユーザー開始型リクエストのベストプラクティスは、 接続ステータスと従量制接続の モニタリングで説明されているように、まず ConnectivityManagerを使用して接続を確認することです。 ネットワークがない場合、アプリはモバイル 無線通信に検索を強制しないことでバッテリーを節約できます。接続が確立されたら、リクエストをスケジュールして、他のリクエストとまとめて実行できます。

接続をプールする

バッチ処理とプリフェッチに加えて、アプリのネットワーク接続をプールすることも有効な方法です。

一般に、新しいネットワーク接続を開始するよりも既存のネットワーク接続を再利用する方が効率的です。また、接続を再利用すると、輻輳やそれに関連するネットワーク データの問題に対してネットワークがよりインテリジェントに対応できます。

HttpURLConnectionOkHttp などのほとんどの HTTP クライアントでは、デフォルトで接続プーリングが有効になっており、複数の リクエストで同じ接続を再利用できます。

まとめと今後の展望

このセクションでは、無線通信と、バッテリーの消耗を抑えながら高速でレスポンシブなユーザー エクスペリエンスを提供するために幅広く適用できる戦略について説明しました。

次のセクションでは、ほとんどのアプリに共通する 3 種類のネットワーク インタラクションについて詳しく説明します。これらの各タイプのドライバと、これらのインタラクションを効率的に管理するための最新の手法と API について説明します。