事例紹介

WHOOP が過度の部分的な wake lock セッションを 90% 以上削減した方法

所要時間: 4 分

ウェアラブル向けの Android アプリを開発する場合、画面がオフになったときからが本番です。WHOOP は、トレーニング、回復、睡眠、ストレスに対する体の反応をメンバーが把握できるようにサポートしています。Android を利用する多くの WHOOP メンバーにとって、信頼性の高いバックグラウンド同期と接続性は、こうした分析情報を得るために不可欠な要素です。

今年初め、Google Play は Android Vitals の新しい指標として、過度な部分 wake lock をリリースしました。この指標は、24 時間の間に、除外対象外の wake lock の累積使用時間が 2 時間を超えたユーザー セッションの割合を測定します。この指標の目的は、バッテリーを消耗させる可能性のある原因を特定して対処できるようにすることです。これは、優れたユーザー エクスペリエンスを提供するうえで不可欠です。

2026 年 3 月 1 日以降、品質しきい値を満たしていないアプリは、Google Play のディスカバリー サーフェスから除外される可能性があります。また、Google Play ストアの掲載情報に、アプリのバッテリー使用量が想定より多い可能性があることを示す警告が表示されることもあります。

WHOOP のシニア Android エンジニアである Mayank Saini 氏によると、Android Vitals でアプリの過度な部分的な wake lock の割合が 15%(推奨されるしきい値の 5% を超える)と報告されたことで、「チームは Android の効率性を高める機会を得た」とのことです。

mayank.png

チームは、Android Vitals の指標を、バックグラウンド処理が CPU を必要以上に長く起動させていることを示す明確なシグナルと見なしました。この問題を解決することで、優れたユーザー エクスペリエンスを維持しながら、バックグラウンドでの無駄な時間を減らし、信頼性が高くタイムリーな Bluetooth 接続と同期を維持できるようになります。

問題の特定

どこから着手すべきかを判断するため、チームはまず Android Vitals を利用して、どの wake lock が指標に影響を与えているかについて分析情報を得ました。Android Vitals の過度の部分的な wake lock ダッシュボードを参照したところ、過度の部分的な wake lock の最大の原因が、WorkManager ワーカーの 1 つ(ダッシュボードでは androidx.work.impl.background.systemjob.SystemJobService と表示)であることがわかりました。WHOOP の「常時接続エクスペリエンス」をサポートするため、アプリは WorkManager を使用して、定期的な同期やウェアラブルへの定期的な更新の配信などのバックグラウンド タスクを実行しています。

チームは、WorkManager がバックグラウンドでタスクを実行する際にwake lock を取得することを認識していましたが、Android Vitals に過剰な部分 wake lock の指標が導入されるまで、すべてのバックグラウンド処理(WorkManager 以外も含む)がどのように分散されているかを把握できませんでした。

ダッシュボードで WorkManager が主な原因であることが特定されたため、チームは最も影響を与えているワーカーを特定し、問題の解決に取り組むことに集中できました。

内部指標とデータを使用して原因を絞り込む

WHOOP には、WorkManager の指標をモニタリングするための内部インフラストラクチャがすでに設定されていました。定期的にモニタリングする項目は次のとおりです。

  1. 平均実行時間: ワーカーの実行時間。
  2. タイムアウト: ワーカーが完了せずにタイムアウトする頻度はどのくらいですか?
  3. 再試行: 作業がタイムアウトまたは失敗した場合、ワーカーはどのくらいの頻度で再試行しますか?
  4. キャンセル: 作業がキャンセルされた頻度。

ワーカーの成功と失敗だけでなく、それ以上のことを追跡することで、チームは作業の効率性を把握できます。

内部指標により、一部のワーカーで平均実行時間が長いことが判明し、調査をさらに絞り込むことができました。

チームは、内部指標に加えて、Android Studio のBackground Task Inspector を使用して、対象のワーカーを検査、デバッグしました。特に、関連する wake lock に焦点を当て、Android Vitals でフラグが付けられた指標に合わせました。

調査: ワーカー バリアントの区別

WHOOP は、一部のワーカーに 1 回限りのスケジュールと定期的なスケジュールを使用しています。これにより、アプリは、同じ成功基準を持つ同一のタスクに対して、同じ Worker ロジックを再利用できます。異なるのはタイミングだけです。

内部指標を使用することで、特定のワーカーに検索を絞り込むことができましたが、ワーカーが 1 回限り、定期的、またはその両方の場合にバグが発生したかどうかはわかりませんでした。そこで、WorkManager の setTraceTag メソッドを使用して、同じ Worker の 1 回限りのバリアントと定期的なバリアントを区別するアップデートをリリースしました。

この追加の詳細により、過剰な部分 wake lock を伴うセッションに最も寄与している Worker バリアント(定期的または 1 回限り)を明確に特定できます。しかし、データを確認したところ、どちらのバリエーションも他方より貢献しているようには見えないことがわかり、チームは驚きました。

WHOOP の Android エンジニア II である Manmeet Tuteja 氏は、「この分割により、問題が両方のバリアントで発生していることを確認できました。これは、スケジューリング構成ではなく、ワーカー実装内の共有ビジネス ロジックの問題であることを示しています」と述べています。

manmeet.png

ワーカーの動作を深く掘り下げ、根本原因を修正する

ワーカー内のロジックを調べる必要があることがわかったため、チームは調査中にフラグが付けられたワーカーの動作を再確認しました。具体的には、作業が停滞して完了していない可能性があるインスタンスを探していました。

これらすべてが、過剰な wake lock の根本原因の特定につながりました。

WHOOP センサーへの接続を待ってから処理を進めるように設計された CoroutineWorker。 

センサーが接続されていない状態で作業が開始された場合、whoopSensorFlow(センサーが接続されているかどうかを示す)は null でした。SensorWorker はこれを早期終了条件として扱わず、実行を継続し、実質的に接続を無期限に待機していました。その結果、WorkManager は処理がタイムアウトするまで部分的な wake lock を保持し、バックグラウンドでの wake lock の使用量が増加し、SensorWorker の不要な再スケジュールが頻繁に発生していました。

これに対処するため、WHOOP チームは、コア ビジネス ロジックの実行を試みる前に接続ステータスを確認するよう、ワーカー ロジックを更新しました。

センサーが利用できない場合、ワーカーは終了し、タイムアウト シナリオを回避して wake lock を解放します。次のコード スニペットは、この解決策を示しています。

class SensorWorker(appContext: Context, params: WorkerParameters): CoroutineWorker(appContext, params) {
   override suspend fun doWork(): Result {
      ...
      // Check the sensor state and perform work or return failure
       return whoopSensorFlow.replayCache
            .firstOrNull()
            ?.let { cachedData ->
                processSensorData(cachedData)
                Result.success()
            } ?: run {
                Result.failure()
            }
}

過度の部分的な wake lock が発生するセッションを 90% 削減

修正をリリースした後も、チームは Android Vitals ダッシュボードをモニタリングして、変更の影響を確認しました。

最終的に、WHOOP は Worker への変更を実装してからわずか 30 日で、過剰な部分 wake lock の割合を 15% から 1%未満に削減することに成功しました。 

partialWake.png

この変更により、完了せずにタイムアウトする作業のインスタンスが減り、平均実行時間が短縮されました。

バックグラウンド処理の効率を改善したいと考えている他のデベロッパーに対する WHOOP チームのアドバイスは次のとおりです。

sarthak.png

使ってみる

アプリの過度な部分 wake lock を減らしたり、ワーカーの効率を改善したりしたい場合は、Android Vitals でアプリの過度な部分 wake lock 指標を確認し、wake lock のドキュメントでベスト プラクティスとデバッグ戦略を確認してください。

作成者:
続きを読む