Jak i dlaczego opracowaliśmy statystyki skuteczności

W Chrome 102 w Narzędziach deweloperskich znajdziesz nowy, eksperymentalny panel – Statystyki wydajności. W tym poście porozmawiamy nie tylko o tym, dlaczego pracujemy nad nowym panelem, ale też o wyzwaniach technicznych, na które się natknęliśmy, i podjętych przez nas decyzjach.

ALT_TEXT_HERE

Po co tworzyć kolejny panel?

Udostępniliśmy film, w którym wyjaśniamy, dlaczego warto utworzyć panel Statystyki skuteczności i jak za jego pomocą uzyskać przydatne statystyki dotyczące wydajności witryny.

Dotychczasowy Panel skuteczności jest świetnym rozwiązaniem, jeśli chcesz zobaczyć wszystkie dane o swojej witrynie w jednym miejscu. Jednak uznaliśmy, że może to być trochę przytłaczające. Jeśli nie jesteś ekspertem od skuteczności, trudno jest stwierdzić, czego szukać i które fragmenty nagrania są istotne.

Otwórz panel Trendy, w którym nadal możesz wyświetlać oś czasu logu czasu i sprawdzać dane, a także korzystać z praktycznej listy narzędzi dla deweloperów, które według nich są głównymi „statystykami”, którymi warto się przyjrzeć. Statystyki zidentyfikują takie problemy, jak żądania blokujące renderowanie, przesunięcia układu i długie zadania, które mogą negatywnie wpływać na szybkość wczytywania stron w witrynie, a zwłaszcza na jej podstawowy wskaźnik internetowy (CWV). Oprócz zgłaszania problemów Statystyki skuteczności zawierają praktyczne sugestie, jak poprawić wyniki CWV, a także linki do dodatkowych materiałów i dokumentacji.

Link do przesyłania opinii w panelu

Ten panel jest w wersji eksperymentalnej i czekamy na Twoją opinię. Daj nam znać, jeśli zauważysz błędy lub będziesz mieć prośbę o dodanie funkcji, które Twoim zdaniem mogą pomóc w poprawie wydajności Twojej witryny.

Jak tworzymy statystyki skuteczności

Podobnie jak pozostałe narzędzia deweloperskie, do stworzenia interfejsu użytkownika stworzyliśmy statystyki wydajności w języku TypeScript, a do stworzenia interfejsu użytkownika użyliśmy komponentów sieciowych, opartych na lit-html. Statystyki skuteczności różnią się tym, że podstawowy interfejs UI jest elementem HTML canvas, a oś czasu jest rysowana na tej przestrzeni roboczej. Duża złożoność wynika z zarządzania obszarem roboczym, a nie tylko rysowania właściwych danych w odpowiednim miejscu, ale także zarządzania zdarzeniami myszy (na przykład: gdzie użytkownik kliknął obszar roboczy? Czy kliknęli narysowane przez nas zdarzenie?) i zadbaliśmy o skuteczne ponowne wyrenderowanie obszaru roboczego.

Wiele ścieżek na jednym obszarze roboczym

Każda witryna ma wiele „ścieżek” do wyrenderowania, z których każdy reprezentuje inną kategorię danych. Na przykład w panelu Statystyki domyślnie wyświetlają się 3 ścieżki:

Zamierzamy dodawać kolejne ścieżki dźwiękowe w miarę udostępniania panelu.

Początkowo myśleliśmy, że każdy z tych ścieżek ma renderować własny obiekt <canvas>, aby w widoku głównym znajdowało się wiele elementów canvas ułożonych w pionie. Uprości to renderowanie na poziomie ścieżki, ponieważ każda ścieżka może być renderowana oddzielnie i nie będzie narażone na niebezpieczeństwo wyrenderowania ścieżki poza jej granicami. Niestety w tym przypadku występują 2 główne problemy:

Renderowanie (ponowne) elementów canvas jest kosztowne. Posiadanie wielu płótna kosztuje więcej niż 1 odbitki na płótnie, nawet jeśli jest ona większa. Renderowanie nakładek, które przechodzą przez wiele ścieżek (np. pionowe linie w celu oznaczenia zdarzeń, takie jak czas FCP), staje się skomplikowane: musimy renderować je na wielu obszarach roboczych i dbać o to, by były renderowane razem i prawidłowo wyrównane.

Użycie 1 elementu canvas w całym interfejsie oznaczało, że musieliśmy się zastanowić, jak sprawić, by każda ścieżka renderowała się we właściwych współrzędnych i nie przechodzi na inną ścieżkę. Na przykład, jeśli ścieżka ma wysokość 100 pikseli, nie możemy zezwolić na wyrenderowanie czegoś o wysokości 120 pikseli i dopełnienie jej obszaru znajdującego się pod nią. Aby rozwiązać ten problem, możemy użyć konta clip. Przed wyrenderowaniem każdej ścieżki rysujemy prostokąt, który reprezentuje widoczne okno ścieżki. Dzięki temu wszystkie ścieżki narysowane poza tymi granicami będą przycinane przez obszar roboczy.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

Nie chcieliśmy też, aby każda ścieżka znała swoją pozycję w pionie: każda ścieżka powinna renderować się tak, jakby była renderowana w punkcie 0, 0. Ponadto mamy komponent wyższego poziomu (nazywany TrackManager), który zarządza ogólną pozycją ścieżki. Można to zrobić za pomocą narzędzia translate, które tłumaczy obszar roboczy o określoną pozycję (x, y). Na przykład:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

Mimo że w kodzie rect położenie jest ustawione na 0, 0, ogólne tłumaczenie spowoduje, że prostokąt będzie renderowany na 0, 10. Dzięki temu możemy pracować na podstawie ścieżki, tak jakby renderowanie było renderowane w miejscu (0, 0), i zostać tłumaczone przez naszego menedżera ścieżek podczas renderowania każdej z nich. Dzięki temu mamy pewność, że każda ścieżka jest prawidłowo renderowana poniżej poprzedniej.

Odbitki na płótnie z utworami i najciekawszymi momentami

Renderowanie w obszarze roboczym jest stosunkowo drogie i chcemy, aby panel Trendy działał płynnie i elastycznie, gdy będziesz z niego korzystać. Czasami nie można uniknąć ponownego wyrenderowania całego obszaru roboczego. Na przykład po zmianie poziomu powiększenia musimy zacząć od nowa i ponownie wyrenderować wszystko. Ponowne renderowanie w Canvas jest szczególnie kosztowne, ponieważ nie można po prostu wyrenderować tylko niewielkiego fragmentu tekstu – trzeba wyczyścić całą przestrzeń roboczą i ponownie narysować. Różni się to od ponownego renderowania DOM, w którym narzędzia mogą obliczyć minimalną wymaganą nakład pracy i nie usuwać wszystkiego, aby zacząć od nowa.

Jednym z obszarów, w których napotkaliśmy problemy wizualne, było wyróżnianie. Gdy najeżdżasz kursorem na dane w panelu, podświetlamy je na osi czasu, a po najechaniu kursorem na Statystyki danego zdarzenia rysujemy niebieskie obramowanie wokół tego zdarzenia.

Ta funkcja najpierw wykrywała ruch kursora myszy nad elementem, który wywołuje podświetlenie, a następnie rysował go bezpośrednio na głównym obszarze roboczym. Problem pojawia się, gdy musimy usunąć podświetlenie. Jedyną opcją jest ponowne przerysowanie wszystkiego. Nie da się po prostu przerysować obszaru, w którym znajdował się najciekawszy moment (ale nie bez wielkich zmian architektonicznych), ale od nowa narysować cały płótno tylko dlatego, że chcemy usunąć niebieskie obramowanie wokół jednego elementu, które wydaje się przesadzone. Opóźniał się również przy szybkim przesuwaniu myszą po różnych elementach w celu wyświetlenia kilku podświetleń w krótkich odstępach czasu.

Aby rozwiązać ten problem, podzieliliśmy nasz interfejs na 2 obszary robocze poza ekranem: „główną”, gdzie są renderowane ścieżki, i obszar z najciekawszymi momentami, gdzie rysowane są podświetlenia. Następnie renderujemy, kopiując te obszary robocze na pojedynczą przestrzeń roboczą, która jest widoczna na ekranie dla użytkownika. Możemy użyć metody drawImage w kontekście obiektu canvas, który może pobierać inny obszar roboczy jako źródło.

Oznacza to, że usunięcie zaznaczenia nie spowoduje ponownego narysowania głównego obszaru roboczego. Zamiast tego możemy wyczyścić obszar roboczy ekranu, a następnie skopiować główny obszar roboczy na widoczny obszar roboczy. Kopiowanie obszaru roboczego jest tanie, a rysunek jest kosztowny, więc przeniesienie wyróżnionych elementów na inny obszar roboczy pozwala uniknąć tych kosztów przy włączaniu i wyłączaniu podświetleń.

Kompleksowo przetestowana analiza logów czasu

Jedną z zalet tworzenia nowej funkcji od zera jest możliwość zastanowienia się nad wprowadzonymi wcześniej wyborami technicznymi i wprowadzeniem ulepszeń. Jedną z rzeczy, które chcieliśmy poprawić, było wyraźne podzielenie kodu na dwie niemal całkowicie odrębne części:

Przeanalizuj plik śledzenia i wyciągnij wymagane dane. Renderuj zbiór ścieżek.

Oddzielenie analizy (część 1) od pracy w interfejsie (część 2) pozwoliło nam stworzyć solidny system analizy. Każdy ślad jest przetwarzany przez serię modułów obsługi, które odpowiadają za różne kwestie: funkcja LayoutShiftHandler oblicza wszystkie informacje potrzebne do przesunięcia układu, a NetworkRequestsHandler tylko do pobierania żądań sieciowych. Ten jawny etap analizy, w ramach którego mamy różne moduły obsługi odpowiedzialne za różne części logu czasu, również przyniósł korzyści: analiza logów czasu bywa bardzo skomplikowana i pomaga skupić się na jednym problemie naraz.

Jesteśmy też w stanie dokładnie przetestować analizę logów czasu, rejestrując nagrania w Narzędziach deweloperskich, zapisując je i wczytując w ramach naszego pakietu testowego. To świetne rozwiązanie, bo możemy przeprowadzać testy na prawdziwych śladach i nie gromadzić ogromnych ilości fałszywych danych, które mogłyby stać się nieaktualne.

Zrzut ekranu z interfejsem Canvas

Pozostając przy testowaniu, zwykle testujemy nasze komponenty frontendu, renderując je w przeglądarce i upewniając się, że działają zgodnie z oczekiwaniami. Możemy wysyłać zdarzenia kliknięcia w celu aktywowania aktualizacji i potwierdzać, że DOM generowany przez komponenty jest prawidłowy. Takie podejście sprawdza się w naszym przypadku, ale nie ma zastosowania, gdy rozważamy renderowanie na płótnie – nie ma sposobu na sprawdzenie obszaru roboczego i ustalenie, co jest na nim narysowane. W związku z tym nasze standardowe podejście do renderowania i wysyłania zapytań nie jest więc odpowiednie.

Aby przeprowadzić test, przerobiliśmy zrzuty ekranu. Każdy test powoduje uruchomienie obszaru roboczego, wyrenderowanie ścieżki, którą chcemy przetestować, a następnie wykonanie zrzutu ekranu elementu canvas. Zrzut ekranu jest następnie zapisywany w naszej bazie kodu i w przyszłości porównamy zapisany zrzut ekranu z wygenerowanym przez niego zrzutem ekranu. Jeśli zrzuty ekranu będą się różnić, test się nie powiedzie. Udostępniamy też flagę uruchamiającą test i wymuszając aktualizację zrzutu ekranu, gdy celowo zmieniliśmy renderowanie i chcemy zaktualizować test.

Testy zrzutów ekranu nie są doskonałe i są nieco niejasne. Możesz jedynie sprawdzić, czy cały komponent renderuje się zgodnie z oczekiwaniami, a nie bardziej szczegółowe stwierdzenia. Na początku mieliśmy do czynienia z nadużywaniem ich w celu zapewnienia prawidłowego renderowania każdego komponentu (HTML lub canvas). Bardzo spowalniało to działanie naszego pakietu testowego i doprowadziło do sytuacji, w której drobne, niemal nieistotne zmiany w interfejsie (np. subtelne zmiany kolorów czy dodawanie marginesów między elementami) powodowały błędy i wymagały aktualizacji wielu zrzutów ekranu. Teraz ograniczyliśmy użycie zrzutów ekranu i wykorzystaliśmy je wyłącznie w przypadku komponentów opartych na obiektach canvas. Do tej pory to rozwiązanie dobrze się sprawdzało.

Podsumowanie

Utworzenie nowego panelu statystyk dotyczących skuteczności było dla zespołu bardzo przyjemnym i edukacyjnym doświadczeniem. Dowiedzieliśmy się sporo o plikach śledzenia, pracy z obszarami roboczymi i nie tylko. Mamy nadzieję, że nowy panel Ci się podoba. Chętnie poznamy Twoją opinię.

Więcej informacji o panelu Statystyki skuteczności znajdziesz w artykule Statystyki skuteczności: uzyskaj przydatne statystyki dotyczące wydajności witryny.

Pobieranie kanałów podglądu

Jako domyślnej przeglądarki dla programistów możesz używać Chrome Canary, Dev lub Beta. Te kanały podglądu dają dostęp do najnowszych funkcji Narzędzi deweloperskich, umożliwiają testowanie najnowocześniejszych interfejsów API platform internetowych oraz wykrywanie problemów w witrynie, zanim zdołają zrobić użytkownicy.

Kontakt z zespołem Narzędzi deweloperskich w Chrome

Użyj poniższych opcji, aby omówić nowe funkcje i zmiany w poście lub wszelkie inne kwestie związane z Narzędziami dla deweloperów.

  • Prześlij nam sugestię lub opinię na stronie crbug.com.
  • Aby zgłosić problem z Narzędziami deweloperskimi, kliknij Więcej opcji   Więcej   > Pomoc > Zgłoś problemy z Narzędziami deweloperskimi.
  • zatweetuj na @ChromeDevTools.
  • Napisz komentarz o nowościach w filmach w YouTube dostępnych w Narzędziach deweloperskich lub z poradami dotyczącymi narzędzi dla deweloperów w filmach w YouTube.