Studia przypadków

Jak WHOOP zmniejszył liczbę sesji z nadmiernymi częściowymi blokadami uśpienia o ponad 90%

4 minuty czytania

Tworzenie aplikacji na Androida na urządzenie do noszenia oznacza, że prawdziwa praca zaczyna się, gdy ekran się wyłącza. WHOOP pomaga użytkownikom zrozumieć, jak ich organizm reaguje na trening, regenerację, sen i stres. Dla wielu użytkowników WHOOP na Android niezawodna synchronizacja i łączność w tle są tym, co umożliwia uzyskanie tych informacji.

Na początku tego roku Google Play wprowadził nowy wskaźnik w Android Vitals: nadmierne częściowe blokady uśpienia. Ten wskaźnik mierzy odsetek sesji użytkowników, w których łączne, niezwolnione użycie blokady uśpienia przekracza 2 godziny w ciągu 24 godzin. Celem tego wskaźnika jest pomoc w identyfikowaniu i rozwiązywaniu potencjalnych źródeł szybkiego zużycia baterii, co jest kluczowe dla zapewnienia doskonałych wrażeń użytkownika.

Od 1 marca 2026 r. aplikacje, które nadal nie będą spełniać progu jakości, mogą zostać wykluczone z powierzchni Google Play. Na stronie aplikacji w Sklepie Google Play może też pojawić się ostrzeżenie, że aplikacja może zużywać więcej baterii niż oczekiwano.

Według Mayanka Sainiego, starszego inżyniera Androida w WHOOP, „dało to zespołowi możliwość podniesienia poprzeczki w zakresie wydajności Androida”, ponieważ Android Vitals oznaczył odsetek nadmiernych częściowych blokad uśpienia w aplikacji jako 15%, co przekraczało zalecany próg 5%.

mayank.png

Zespół uznał wskaźnik Android Vitals za wyraźny sygnał, że praca w tle utrzymuje procesor w stanie aktywności dłużej niż to konieczne. Rozwiązanie tego problemu pozwoli im nadal zapewniać doskonałe wrażenia użytkownika, jednocześnie zmniejszając marnowany czas w tle oraz utrzymując niezawodną i szybką łączność Bluetooth i synchronizację.

Identyfikowanie problemu

Aby dowiedzieć się, od czego zacząć, zespół najpierw sprawdził Android Vitals, aby uzyskać więcej informacji o tym, które blokady uśpienia wpływają na ten wskaźnik. Po zapoznaniu się z panelem Android Vitals dotyczącym nadmiernych częściowych blokad uśpienia udało im się ustalić, że największy wpływ na nadmierne częściowe blokady uśpienia ma jedna z klas worker biblioteki WorkManager (w panelu oznaczona jako androidx.work.impl.background.systemjob.SystemJobService). Aby zapewnić „ciągłe działanie” WHOOP, aplikacja używa WorkManager do zadań w tle, takich jak okresowa synchronizacja i dostarczanie powtarzających się aktualizacji do urządzenia do noszenia. 

Zespół wiedział , że WorkManager uzyskuje blokadę uśpienia podczas wykonywania zadań w tle, ale wcześniej nie miał wglądu w to, jak rozkłada się cała praca w tle (nie tylko WorkManager), dopóki w Android Vitals nie wprowadzono wskaźnika nadmiernych częściowych blokad uśpienia.

Gdy panel wskazał WorkManager jako główne źródło problemu, zespół mógł skupić się na ustaleniu, która z klas worker ma największy wpływ na ten wskaźnik, i podjąć działania w celu rozwiązania problemu.

Wykorzystywanie wewnętrznych danych i wskaźników do lepszego zawężenia przyczyny

WHOOP miał już skonfigurowaną infrastrukturę wewnętrzną do monitorowania wskaźników WorkManager. Okresowo monitorują:

  1. Średni czas działania: jak długo działa klasa worker?
  2. Limity czasu: jak często klasa worker przekracza limit czasu zamiast zakończyć działanie?
  3. Ponowne próby: jak często klasa worker podejmuje ponowną próbę, jeśli działanie przekroczyło limit czasu lub się nie powiodło?
  4. Anulowania: jak często działanie zostało anulowane?

Śledzenie nie tylko sukcesów i niepowodzeń klasy worker, ale też innych wskaźników, daje zespołowi wgląd w wydajność jego pracy.

Wskaźniki wewnętrzne wskazywały wysoki średni czas działania w przypadku kilku wybranych klas worker, co pozwoliło zespołowi jeszcze bardziej zawęzić zakres analizy. 

Oprócz wskaźników wewnętrznych zespół używał też inspektora zadań w tlew Android Studio, aby sprawdzać i debugować interesujące klasy worker, ze szczególnym uwzględnieniem powiązanych blokad uśpienia, aby dostosować się do wskaźnika oznaczonego w Android Vitals.

Analiza: rozróżnianie wariantów klasy worker

W przypadku niektórych klas worker WHOOP używa zarówno jednorazowego , jak i okresowego planowania. Dzięki temu aplikacja może ponownie wykorzystywać tę samą logikę klasy worker w przypadku identycznych zadań z tymi samymi kryteriami sukcesu, które różnią się tylko czasem.

Korzystanie z wskaźników wewnętrznych umożliwiło zawężenie wyszukiwania do konkretnej klasy worker, ale nie było wiadomo, czy błąd wystąpił, gdy klasa worker była jednorazowa, okresowa czy obie. Dlatego zespół wprowadził aktualizację, aby używać metody setTraceTag w WorkManager do rozróżniania jednorazowych i okresowych wariantów tej samej klasy worker.

Ten dodatkowy szczegół pozwolił zespołowi jednoznacznie określić, który wariant klasy worker (okresowy czy jednorazowy) ma największy wpływ na sesje z nadmiernymi częściowymi blokadami uśpienia. Zespół był jednak zaskoczony, gdy dane wykazały, że żaden z wariantów nie miał większego wpływu niż drugi.

Manmeet Tuteja, inżynier Androida II w WHOOP, powiedział: „Ten podział pomógł nam też potwierdzić, że problem występuje w obu wariantach, co wskazywało na problem ze wspólną logiką biznesową w implementacji klasy worker, a nie na konfigurację planowania”.

manmeet.png

Dogłębne analizowanie zachowania klasy worker i usuwanie głównej przyczyny

Wiedząc, że muszą przyjrzeć się logice wewnątrz klasy worker,  zespół ponownie przeanalizował zachowanie klas worker, które zostały oznaczone podczas analizy. Szczególnie interesowały ich przypadki, w których działanie mogło się zawieszać i nie kończyć.

Wszystko to doprowadziło do znalezienia głównej przyczyny nadmiernych blokad uśpienia:

CoroutineWorker, który został zaprojektowany tak, aby czekać na połączenie z czujnikiem WHOOP przed kontynuowaniem działania. 

Jeśli działanie rozpoczęło się bez podłączonego czujnika, whoopSensorFlow – który wskazuje, czy czujnik jest podłączony – miał wartość null. SensorWorker nie traktował tego jako warunku wczesnego wyjścia i działał dalej, skutecznie czekając na połączenie w nieskończoność. W rezultacie WorkManager utrzymywał częściową blokadę uśpienia do momentu przekroczenia limitu czasu działania, co prowadziło do wysokiego zużycia blokady uśpienia w tle oraz częstego, niechcianego ponownego planowania SensorWorker.

Aby rozwiązać ten problem, zespół WHOOP zaktualizował logikę klasy worker, aby sprawdzać stan połączenia przed próbą wykonania podstawowej logiki biznesowej.

Jeśli czujnik jest niedostępny, klasa worker kończy działanie, unikając przekroczenia limitu czasu i zwalniając blokadę uśpienia. Poniższy fragment kodu przedstawia rozwiązanie:

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

Zmniejszenie liczby sesji z nadmiernymi częściowymi blokadami uśpienia o 90%

Po wprowadzeniu poprawki zespół nadal monitorował panel Android Vitals, aby potwierdzić wpływ zmian. 

Ostatecznie WHOOP zauważył, że odsetek nadmiernych częściowych blokad uśpienia spadł z 15% do mniej niż 1% zaledwie 30 dni po wprowadzeniu zmian w klasie worker. 

partialWake.png

W wyniku zmian zespół zauważył mniej przypadków przekroczenia limitu czasu działania bez jego ukończenia, co spowodowało skrócenie średniego czasu działania. 

Rada zespołu WHOOP dla innych deweloperów, którzy chcą poprawić wydajność pracy w tle:

sarthak.png

Rozpocznij

Jeśli chcesz zmniejszyć liczbę nadmiernych częściowych blokad uśpienia w aplikacji lub poprawić wydajność klasy worker, sprawdź wskaźnik nadmiernych częściowych blokad uśpienia w Android Vitals i zapoznaj się z dokumentacją blokad uśpienia, aby poznać sprawdzone metody i strategie debugowania. 

Autorzy:
Czytaj dalej