Case Studies

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

Czas czytania: 4 minuty

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 udostępnił nowy wskaźnik w Android Vitals: nadmierne częściowe blokady uśpienia. Ten wskaźnik mierzy odsetek sesji użytkowników, w których skumulowane użycie blokad uśpienia (z wyłączeniem wyjątków) przekracza 2 godziny w ciągu 24 godzin. Celem tego wskaźnika jest pomoc w identyfikowaniu i rozwiązywaniu potencjalnych przyczyn szybkiego zużycia baterii, co ma kluczowe znaczenie dla zapewnienia doskonałych wrażeń użytkownikom.

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”. Android Vitals oznaczył bowiem 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żytkownikom, jednocześnie zmniejszając marnowany czas w tle i utrzymując niezawodną oraz szybką łączność i synchronizację Bluetooth.

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 przeanalizowaniu panelu Android Vitals dotyczącego 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 pojawił się wskaźnik nadmiernych częściowych blokad uśpienia.

Gdy panel wskazał WorkManager jako głównego sprawcę, zespół mógł skupić się na ustaleniu, która z klas worker ma największy wpływ na ten problem, i podjąć działania w celu jego rozwiązania.

Wykorzystanie wewnętrznych danych i wskaźników do dokładniejszego określenia przyczyny

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

  1. Średni czas działania: jak długo działa klasa worker?
  2. Przekroczenia limitu 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 danych, daje zespołowi wgląd w skuteczność jego pracy.

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

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

Analiza: rozróżnianie wariantów klasy worker

WHOOP używa zarówno jednorazowego , jak i okresowego planowania w przypadku niektórych klas worker. 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 zespół nie mógł stwierdzić, czy błąd wystąpił, gdy klasa worker była jednorazowa, okresowa, czy w obu przypadkach. W związku z tym zespół wdrożył 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

Dokładniejsze 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ę zawiesić i nie zostać ukończone.

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

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

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 wcześniejszego zakończenia i działał dalej, czekając w nieskończoność na połączenie. W rezultacie WorkManager utrzymywał częściową blokadę uśpienia do momentu przekroczenia limitu czasu działania, co prowadziło do wysokiego zużycia blokad uśpienia w tle oraz częstego, niepożądanego ponownego planowania SensorWorker.

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

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 wdrożeniu poprawki zespół nadal monitorował panel Android Vitals, aby potwierdzić wpływ zmian. 

Ostatecznie, zaledwie 30 dni po wprowadzeniu zmian w klasie worker, WHOOP odnotował spadek odsetka nadmiernych częściowych blokad uśpienia z 15% do mniej niż 1%

partialWake.png

W wyniku tych zmian zespół odnotował 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ć więcej sprawdzonych metod i strategii debugowania. 

Autorzy:
Czytaj dalej