Dowiedz się więcej o pomiarach animacji, klatkach animacji i ogólnej płynności strony.
Pewnie zdarzyło Ci się, że strony „zacinały się” lub „zawieszały” podczas przewijania lub animacji. Mówimy, że te usługi nie są płynne. Aby rozwiązać tego typu problemy, zespół Chrome pracuje nad dodaniem do naszych narzędzi laboratoryjnych większej obsługi wykrywania animacji, a także nad ciągłym ulepszaniem diagnostyki potoku renderowania w Chromium.
Chcielibyśmy podzielić się najnowszymi postępami, przedstawić konkretne wskazówki dotyczące narzędzi i omówić pomysły na przyszłe wskaźniki płynności animacji. Jak zawsze chętnie poznamy Twoją opinię.
W tym poście omówimy 3 główne tematy:
- Szybki przegląd animacji i klatek animacji.
- Nasze obecne przemyślenia na temat pomiaru ogólnej płynności animacji.
- Kilka praktycznych sugestii, które możesz wykorzystać w narzędziach laboratoryjnych.
Czym są animacje?
Animacje ożywiają treści. Dzięki animacjom, zwłaszcza tym, które reagują na interakcje użytkownika, treści mogą wydawać się bardziej naturalne, zrozumiałe i atrakcyjne.
Jednak źle wdrożone animacje lub dodanie zbyt wielu animacji może pogorszyć wrażenia użytkownika i sprawić, że korzystanie z aplikacji nie będzie przyjemne. Prawdopodobnie każdy z nas miał do czynienia z interfejsem, w którym było zbyt wiele „pomocnych” efektów przejścia, które w rzeczywistości utrudniały korzystanie z niego, gdy działały nieprawidłowo. Niektórzy użytkownicy mogą więc preferować ograniczenie ruchu, czyli ustawienie, które należy uwzględnić.
Jak działają animacje?
Przypomnijmy, że potok renderowania składa się z kilku sekwencyjnych etapów:
- Styl: oblicz style, które mają zastosowanie do elementów.
- Układ: generowanie geometrii i pozycji każdego elementu.
- Malowanie: wypełnij piksele każdego elementu w warstwach.
- Kompozycja: rysuje warstwy na ekranie.
Animacje można definiować na wiele sposobów, ale wszystkie działają w zasadzie na jeden z tych sposobów:
- Dostosowywanie właściwości układu.
- Dostosowywanie właściwości malowania.
- Dostosowywanie właściwości kompozycji.
Ponieważ te etapy następują po sobie, ważne jest, aby definiować animacje w odniesieniu do właściwości, które znajdują się dalej w procesie. Im wcześniej w procesie nastąpi aktualizacja, tym większe będą koszty i tym mniejsze prawdopodobieństwo, że przebiegnie ona bezproblemowo. (Więcej informacji znajdziesz w sekcji Wydajność renderowania).
Animowanie właściwości układu może być wygodne, ale wiąże się z kosztami, nawet jeśli nie są one od razu widoczne. Animacje powinny być w miarę możliwości definiowane za pomocą zmian właściwości złożonych.
Zdefiniowanie deklaratywnych animacji CSS lub użycie Web Animations i zapewnienie animowania właściwości złożonych to świetny pierwszy krok do zapewnienia płynnych i wydajnych animacji. Ale to nie gwarantuje płynności, ponieważ nawet wydajne animacje internetowe mają ograniczenia wydajności. Dlatego zawsze warto prowadzić pomiary.
Czym są klatki animacji?
Wyświetlenie zmian w wizualnej reprezentacji strony zajmuje trochę czasu. Zmiana wizualna spowoduje wyświetlenie nowej klatki animacji, która zostanie ostatecznie wyrenderowana na ekranie użytkownika.
Wyświetla aktualizacje w określonych odstępach czasu, dzięki czemu aktualizacje wizualne są grupowane. Wiele wyświetlaczy odświeża się w stałych odstępach czasu, np. 60 razy na sekundę (czyli 60 Hz). Niektóre nowsze wyświetlacze mogą oferować wyższe częstotliwości odświeżania (90–120 Hz staje się standardem). Często te wyświetlacze mogą aktywnie dostosowywać częstotliwość odświeżania w zależności od potrzeb, a nawet oferować w pełni zmienną liczbę klatek na sekundę.
Celem każdej aplikacji, takiej jak gra czy przeglądarka, jest przetworzenie wszystkich tych pakietowych aktualizacji wizualnych i wygenerowanie wizualnie kompletnej klatki animacji w terminie za każdym razem. Pamiętaj, że ten cel jest zupełnie inny niż inne ważne zadania przeglądarki, takie jak szybkie wczytywanie treści z sieci czy wydajne wykonywanie zadań JavaScript.
W pewnym momencie może się okazać, że wprowadzenie wszystkich zmian wizualnych w terminie wyznaczonym przez wyświetlacz jest zbyt trudne. W takim przypadku przeglądarka pomija klatkę. Ekran nie gaśnie, tylko powtarza się. Widzisz tę samą aktualizację wizualną przez nieco dłuższy czas – tę samą klatkę animacji, która była wyświetlana w poprzedniej klatce.
To się zdarza często. Nie musi być nawet zauważalna, zwłaszcza w przypadku treści statycznych lub przypominających dokumenty, które są powszechne w szczególności na platformie internetowej. Utracone klatki stają się widoczne tylko wtedy, gdy występują ważne aktualizacje wizualne, takie jak animacje, w przypadku których potrzebujemy stałego strumienia aktualizacji animacji, aby zapewnić płynny ruch.
Co wpływa na klatki animacji?
Deweloperzy stron internetowych mogą mieć duży wpływ na to, jak szybko i wydajnie przeglądarka renderuje i wyświetla aktualizacje wizualne.
Oto kilka przykładów:
- używanie treści, które są zbyt duże lub wymagają zbyt wielu zasobów, aby można je było szybko zdekodować na urządzeniu docelowym;
- Używanie zbyt wielu warstw wymagających zbyt dużej ilości pamięci GPU.
- definiowanie zbyt złożonych stylów CSS lub animacji internetowych;
- stosowanie wzorców projektowych, które wyłączają optymalizacje szybkiego renderowania;
- Zbyt dużo pracy kodu JS w wątku głównym, co prowadzi do długich zadań blokujących aktualizacje wizualne.
Skąd jednak wiesz, kiedy klatka animacji nie zmieściła się w terminie i spowodowała pominięcie klatki?
Jedną z możliwych metod jest requestAnimationFrame()
odpytywanie, ale ma ono kilka wad. requestAnimationFrame()
lub „rAF” informuje przeglądarkę, że chcesz wykonać animację, i prosi o możliwość zrobienia tego przed następnym etapem malowania w potoku renderowania. Jeśli funkcja wywołania zwrotnego nie zostanie wywołana w oczekiwanym czasie, oznacza to, że nie wykonano malowania i pominięto co najmniej jedną klatkę. Sprawdzając i zliczając, jak często wywoływana jest funkcja rAF, możesz obliczyć rodzaj wskaźnika „klatki na sekundę” (FPS).
let frameTimes = [];
function pollFramesPerSecond(now) {
frameTimes = [...frameTimes.filter(t => t > now - 1000), now];
requestAnimationFrame(pollFramesPerSecond);
console.log('Frames per second:', frameTimes.length);
}
requestAnimationFrame(pollFramesPerSecond);
Korzystanie z requestAnimationFrame()
odpytywania nie jest dobrym pomysłem z kilku powodów:
- Każdy skrypt musi skonfigurować własną pętlę odpytywania.
- Może blokować ścieżkę krytyczną.
- Nawet jeśli odpytywanie rAF jest szybkie, może uniemożliwić
requestIdleCallback()
zaplanowanie długich bloków bezczynności, gdy jest używane w sposób ciągły (bloki, które przekraczają jedną klatkę). - Podobnie brak długich bloków bezczynności uniemożliwia przeglądarce zaplanowanie innych długotrwałych zadań (takich jak dłuższe odśmiecanie pamięci i inne zadania wykonywane w tle lub spekulatywnie).
- Jeśli odpytywanie jest włączane i wyłączane, możesz przegapić przypadki, w których przekroczono budżet klatek.
- Odpytywanie będzie zgłaszać fałszywe alarmy w przypadkach, gdy przeglądarka używa zmiennej częstotliwości aktualizacji (np. z powodu stanu zasilania lub widoczności).
- A co najważniejsze, nie rejestruje wszystkich typów aktualizacji animacji.
Zbyt duża ilość pracy w wątku głównym może wpłynąć na możliwość wyświetlania klatek animacji. Sprawdź Jank Sample, aby zobaczyć, jak animacja oparta na rAF, gdy w wątku głównym jest zbyt dużo pracy (np. układ), prowadzi do pominięcia klatek i mniejszej liczby wywołań zwrotnych rAF oraz niższego FPS.
Gdy wątek główny jest przeciążony, aktualizacje wizualne zaczynają się zacinać. To jest szajs!
Wiele narzędzi pomiarowych koncentruje się na możliwości szybkiego zwalniania głównego wątku i płynnego działania klatek animacji. Ale to nie wszystko. Przyjrzyj się temu przykładowi:
Powyższy film pokazuje stronę, która okresowo wstawia długie zadania do wątku głównego. Długie zadania całkowicie uniemożliwiają stronie wyświetlanie niektórych typów aktualizacji wizualnych. W lewym górnym rogu widać spadek zgłaszanej liczby klatek na sekundę do 0.requestAnimationFrame()
Mimo tych długich zadań strona nadal przewija się płynnie. Dzieje się tak, ponieważ w nowoczesnych przeglądarkach przewijanie jest często wielowątkowe i w całości kontrolowane przez kompozytor.
To przykład, w którym na głównym wątku występuje wiele pominiętych klatek, ale na wątku kompozytora jest wiele klatek przewijania, które zostały dostarczone. Po zakończeniu długotrwałego zadania aktualizacja malowania w głównym wątku nie ma do zaoferowania żadnych zmian wizualnych. Odpytywanie rAF sugerowało spadek liczby klatek do 0, ale wizualnie użytkownik nie zauważyłby różnicy.
W przypadku klatek animacji sytuacja nie jest tak prosta.
Klatki animacji: ważne aktualizacje
Powyższy przykład pokazuje, że historia jest bardziej złożona niż tylko requestAnimationFrame()
.
Kiedy aktualizacje animacji i klatki animacji mają znaczenie? Oto niektóre kryteria, które bierzemy pod uwagę. Chętnie poznamy Twoją opinię na ich temat:
- Aktualizacje wątku głównego i wątku kompozytora
- Brakujące aktualizacje lakieru
- Wykrywanie animacji
- Jakość a ilość
Aktualizacje wątku głównego i wątku kompozytora
Aktualizacje klatek animacji nie są wartościami logicznymi. Nie jest tak, że klatki mogą być tylko całkowicie pomijane lub całkowicie wyświetlane. Istnieje wiele powodów, dla których klatka animacji może być częściowo wyświetlana. Innymi słowy, może jednocześnie zawierać nieaktualne treści i nowe aktualizacje wizualne.
Najczęstszy przykład to sytuacja, w której przeglądarka nie może wygenerować nowej aktualizacji głównego wątku w terminie klatki, ale ma nową aktualizację wątku kompozytora (np. w przypadku przewijania w wielu wątkach, o którym wspominaliśmy wcześniej).
Ważnym powodem, dla którego zaleca się używanie animacji deklaratywnych do animowania właściwości złożonych, jest to, że umożliwia to sterowanie animacją w całości przez wątek kompozytora, nawet gdy wątek główny jest zajęty. Ten typ animacji może nadal wydajnie i równolegle generować aktualizacje wizualne.
Z drugiej strony może się zdarzyć, że aktualizacja wątku głównego będzie dostępna do wyświetlenia dopiero po przekroczeniu kilku terminów klatek. Przeglądarka będzie miała jakąś nową aktualizację, ale może nie być najnowszą.
Ogólnie rzecz biorąc, klatki, które zawierają pewne nowe aktualizacje wizualne, ale nie wszystkie, uważamy za częściowe. Częściowe klatki są dość powszechne. Najlepiej, gdyby częściowe aktualizacje obejmowały przynajmniej najważniejsze zmiany wizualne, takie jak animacje, ale jest to możliwe tylko wtedy, gdy animacje są obsługiwane przez wątek kompozytora.
Brakujące aktualizacje lakieru
Inny rodzaj częściowej aktualizacji występuje, gdy multimedia, takie jak obrazy, nie zostały w pełni zdekodowane i zrasteryzowane przed wyświetleniem klatki.
Nawet jeśli strona jest całkowicie statyczna, przeglądarki mogą nie nadążać z renderowaniem aktualizacji wizualnych podczas szybkiego przewijania. Dzieje się tak, ponieważ pikselowe wersje treści poza widocznym obszarem mogą być odrzucane, aby zaoszczędzić pamięć GPU. Renderowanie pikseli zajmuje czas, a po dużym przewinięciu, np. po szybkim przesunięciu palcem, może potrwać dłużej niż jedna klatka. Jest to powszechnie znane jako checkerboarding.
Przy każdej możliwości renderowania klatki można śledzić, ile najnowszych aktualizacji wizualnych faktycznie pojawiło się na ekranie. Pomiar tej zdolności w wielu klatkach (lub w czasie) jest powszechnie znany jako przepustowość klatek.
Jeśli procesor graficzny jest bardzo obciążony, przeglądarka (lub platforma) może nawet zacząć ograniczać częstotliwość prób aktualizacji wizualnych, a tym samym zmniejszać efektywną liczbę klatek na sekundę. Technicznie może to zmniejszyć liczbę pominiętych aktualizacji klatek, ale wizualnie nadal będzie to wyglądać jak mniejsza przepustowość klatek.
Nie wszystkie rodzaje niskiej przepustowości klatek są jednak niekorzystne. Jeśli strona jest w większości nieaktywna i nie ma na niej aktywnych animacji, niska liczba klatek jest tak samo atrakcyjna wizualnie jak wysoka liczba klatek (a przy tym może oszczędzać baterię).
Kiedy przepustowość klatek ma znaczenie?
Wykrywanie animacji
Wysoka przepustowość klatek ma znaczenie zwłaszcza w okresach, w których występują ważne animacje. Różne typy animacji będą zależeć od aktualizacji wizualnych z określonego wątku (głównego, kompozytora lub roboczego), więc aktualizacja wizualna zależy od tego, czy wątek dostarczy aktualizację w terminie. Mówimy, że dany wątek wpływa na płynność, gdy jest aktywna animacja, która zależy od aktualizacji tego wątku.
Niektóre typy animacji są łatwiejsze do zdefiniowania i wykrycia niż inne. Animacje deklaratywne lub animacje oparte na danych wejściowych użytkownika są łatwiejsze do zdefiniowania niż animacje oparte na JavaScript, które są implementowane jako okresowe aktualizacje właściwości stylu, które można animować.
Nawet w przypadku requestAnimationFrame()
nie zawsze można założyć, że każde wywołanie rAF powoduje aktualizację wizualną lub animację. Na przykład używanie odpytywania rAF tylko do śledzenia liczby klatek na sekundę (jak pokazano powyżej) nie powinno samo w sobie wpływać na pomiary płynności, ponieważ nie ma aktualizacji wizualnej.
Jakość a ilość
Wykrywanie animacji i aktualizacji klatek animacji to tylko część historii, ponieważ rejestruje tylko liczbę aktualizacji animacji, a nie ich jakość.
Podczas oglądania filmu możesz na przykład zobaczyć stałą liczbę klatek na sekundę wynoszącą 60 fps. Technicznie jest to idealnie płynne, ale sam film może mieć niski bitrate lub problemy z buforowaniem w sieci. Nie jest to bezpośrednio uwzględniane w statystykach płynności animacji, ale może być nieprzyjemne dla użytkownika.
Może się też zdarzyć, że gra korzystająca z <canvas>
(być może nawet z techniką płótna poza ekranem, aby zapewnić stałą liczbę klatek na sekundę) będzie technicznie idealnie płynna pod względem klatek animacji, ale nie będzie wczytywać do sceny zasobów gry o wysokiej jakości lub będzie wykazywać artefakty renderowania.
Oczywiście witryna może po prostu zawierać bardzo słabe animacje. 🙂
Chyba były całkiem fajne jak na tamte czasy.
Stany pojedynczej klatki animacji
Klatki mogą być wyświetlane częściowo lub mogą być pomijane w sposób, który nie wpływa na płynność, dlatego zaczęliśmy traktować każdą klatkę jako mającą ocenę kompletności lub płynności.
Oto spektrum sposobów, w jakie interpretujemy stan pojedynczej klatki animacji, uporządkowane od najlepszego do najgorszego przypadku:
Nie chcę aktualizacji | Czas bezczynności, powtórzenie poprzedniej klatki. |
W pełni wyświetlona | Aktualizacja głównego wątku została zatwierdzona w terminie lub nie była wymagana. |
Częściowo wyświetlono | Tylko kompozytor; opóźniona aktualizacja wątku głównego nie spowodowała żadnych zmian wizualnych. |
Częściowo wyświetlono | Tylko kompozytor; w wątku głównym nastąpiła aktualizacja wizualna, ale nie obejmowała ona animacji, która wpływa na płynność. |
Częściowo wyświetlono | Tylko kompozytor; w głównym wątku nastąpiła aktualizacja wizualna, która wpływa na płynność, ale zamiast niej użyto wcześniej nieaktualnej klatki. |
Częściowo wyświetlono | Tylko kompozytor; bez głównej aktualizacji, a aktualizacja kompozytora zawiera animację, która wpływa na płynność. |
Częściowo wyświetlono | Tylko kompozytor, ale aktualizacja kompozytora nie zawiera animacji, która wpływa na płynność. |
Pominięta klatka | Brak aktualizacji. Nie było potrzeby aktualizowania kompozytora, a główny wątek został opóźniony. |
Pominięta klatka | Chcieliśmy zaktualizować kompozytora, ale to się opóźniło. |
Stale frame | Aktualizacja była potrzebna i została wygenerowana przez moduł renderujący, ale procesor graficzny nie wyświetlił jej przed upływem terminu synchronizacji pionowej. |
Te stany można przekształcić w rodzaj wyniku. Można ją interpretować jako prawdopodobieństwo, że użytkownik zauważy problem. Pojedyncza utracona klatka może być niezauważalna, ale sekwencja wielu utraconych klatek, która wpływa na płynność, z pewnością będzie widoczna.
Połączenie: wskaźnik procentowy utraconych klatek
Czasami konieczne jest szczegółowe zbadanie stanu każdej klatki animacji, ale przydatne jest też przypisanie szybkiej oceny „na pierwszy rzut oka” do wrażeń użytkownika.
Ponieważ klatki mogą być częściowo wyświetlane, a nawet całkowicie pominięte aktualizacje klatek mogą w rzeczywistości nie wpływać na płynność, chcemy skupić się nie tylko na zliczaniu klatek, ale też na zakresie, w jakim przeglądarka nie jest w stanie dostarczyć wizualnie kompletnych aktualizacji w odpowiednim momencie.
Model myślowy powinien się zmienić z:
- Klatki na sekundę,
- wykrywanie brakujących i ważnych aktualizacji animacji,
- Odsetek odrzuceń w danym okresie.
Istotne jest proporcja czasu oczekiwania na ważne aktualizacje. Uważamy, że odpowiada to naturalnemu sposobowi, w jaki użytkownicy oceniają płynność treści internetowych w praktyce. Do tej pory używaliśmy tych danych jako początkowego zestawu:
- Średni odsetek pominiętych klatek: dla wszystkich klatek animacji, które nie są bezczynne, w całej osi czasu.
- Najgorszy przypadek procentu utraconych klatek: pomiar w 1-sekundowych przedziałach czasowych.
- 95. percentyl odsetka utraconych klatek: mierzony w 1-sekundowych oknach czasowych.
Te wyniki są już dostępne w niektórych narzędziach dla deweloperów w Chrome. Chociaż te dane dotyczą tylko ogólnej przepustowości klatek, oceniamy też inne czynniki, takie jak opóźnienie klatek.
Wypróbuj to w narzędziach dla programistów.
Wyświetlacz HUD
Chromium ma przydatny HUD wydajności ukryty za flagą (chrome://flags/#show-performance-metrics-hud
). Znajdziesz w nim aktualne wyniki dotyczące m.in. podstawowych wskaźników internetowych, a także kilka eksperymentalnych definicji płynności animacji opartych na procentowym spadku liczby klatek w czasie.
Statystyki renderowania klatek
Włącz „Statystyki renderowania klatek” w Narzędziach deweloperskich w ustawieniach renderowania, aby wyświetlać na żywo nowe klatki animacji, które są oznaczone kolorami, aby odróżnić częściowe aktualizacje od aktualizacji w pełni pominiętych klatek. Podawana liczba klatek na sekundę dotyczy tylko w pełni wyświetlonych klatek.
Przeglądarka klatek w nagraniach profilu wydajności w Narzędziach deweloperskich
Panel Wydajność w Narzędziach deweloperskich od dawna ma przeglądarkę klatek. Jednak z czasem przestał on odzwierciedlać sposób działania nowoczesnego potoku renderowania. Niedawno wprowadziliśmy wiele ulepszeń, nawet w najnowszej wersji Chrome Canary, które naszym zdaniem znacznie ułatwią debugowanie problemów z animacjami.
Obecnie klatki w przeglądarce klatek są lepiej dopasowane do granic synchronizacji pionowej i oznaczone kolorami w zależności od stanu. Nie ma jeszcze pełnej wizualizacji wszystkich opisanych powyżej niuansów, ale w najbliższej przyszłości planujemy dodać więcej informacji.
Śledzenie w Chrome
Wreszcie dzięki śledzeniu w Chrome, czyli narzędziu do szczegółowej analizy, możesz zarejestrować ślad „Renderowanie treści internetowych” za pomocą nowego interfejsu Perfetto (lub about:tracing
) i dokładnie przeanalizować potok graficzny Chrome. Może to być trudne zadanie, ale w Chromium pojawiło się ostatnio kilka funkcji, które je ułatwiają. Przegląd dostępnych opcji znajdziesz w dokumencie Cykl życia klatki.
Dzięki zdarzeniom śledzenia możesz jednoznacznie określić:
- które animacje są uruchomione (za pomocą zdarzeń o nazwie
TrackerValidation
); - Uzyskiwanie dokładnej osi czasu klatek animacji (za pomocą zdarzeń o nazwie
PipelineReporter
). - W przypadku aktualizacji animacji, które nie działają płynnie, sprawdź, co dokładnie uniemożliwia szybsze działanie animacji (korzystając z podziału zdarzeń w zdarzeniach
PipelineReporter
). - W przypadku animacji opartych na danych wejściowych sprawdź, ile czasu zajmuje uzyskanie aktualizacji wizualnej (za pomocą zdarzeń o nazwie
EventLatency
).
Co dalej?
Inicjatywa Wskaźniki internetowe ma na celu dostarczanie danych i wskazówek dotyczących tworzenia witryn, które zapewniają użytkownikom jak najlepsze wrażenia. Dane laboratoryjne, takie jak Total Blocking Time (TBT), są niezbędne do wykrywania i diagnozowania potencjalnych problemów z interaktywnością. Planujemy opracować podobne dane laboratoryjne dotyczące płynności animacji.
Będziemy Cię informować o postępach w pracy nad pomysłami na opracowanie kompleksowego wskaźnika na podstawie danych poszczególnych klatek animacji.
W przyszłości chcemy też zaprojektować interfejsy API, które umożliwią wydajne pomiary płynności animacji w przypadku rzeczywistych użytkowników w terenie i w laboratorium. Będziemy o tym informować na bieżąco.
Prześlij opinię
Cieszymy się z ostatnich ulepszeń i narzędzi dla deweloperów, które zostały wprowadzone w Chrome, aby mierzyć płynność animacji. Wypróbuj te narzędzia, porównaj swoje animacje i daj nam znać, co o nich myślisz.
Możesz przesłać swoje uwagi do grupy Google web-vitals-feedback, wpisując w temacie „[Smoothness Metrics]”. Chętnie poznamy Twoją opinię.