Treści na tej stronie zostały przetłumaczone przy użyciu sztucznej inteligencji (AI) lub technologii tłumaczenia maszynowego i mogą zawierać błędy.

Skip to content

30-krotna poprawa wykorzystania pamięci front-endowej podczas ładowania karuzeli

W drugim kwartale 2020 roku przeprowadziliśmy refaktoryzację techniczną strony z doświadczeniami, przepisując ją na React i wykorzystując REST API. Jednak podczas wdrażania natrafiliśmy na interesujący problem.

Na stronie z doświadczeniami znajduje się około 20 karuzeli, z których każda zawiera co najmniej 60 kafelków. Strona wyświetla więc ponad 1200 doświadczeń, w tym istotne informacje, takie jak tytuł, ocena użytkowników, liczba jednoczesnych użytkowników i miniaturka. W każdej karuzeli kliknięcie na prawym przewijaczu wysyła żądanie, aby załadować kolejną partię doświadczeń, jeśli są one dostępne. Następnie nowe dane wynikające z żądania zostaną dołączone do karuzeli, co oznacza dodanie większej liczby węzłów do DOM i renderowanie większej liczby miniatur w przeglądarce. Zużycie pamięci w przeglądarce będzie rosło w miarę przewijania przez użytkowników w celu żądania kolejnych danych, a następnie interfejs użytkownika zwolni i zacznie się opóźniać.

Profil pamięci

Możemy użyć narzędzi programistycznych Chrome, aby zbadać ten problem. Pierwszy zrzut ekranu jest wykonywany podczas początkowego ładowania strony, a drugi po 12 kliknięciach przycisku przewijania w jednej karuzeli. Widzimy wzrost zużycia pamięci o prawie 9,7 MB spowodowany ponad 100 węzłami łańcuchowymi oraz zwiększonym renderowaniem miniatur.

Rozwiązanie

Podczas przewijania karuzeli użytkownicy widzą tylko elementy z okna karuzeli. Na przykład na laptopie o rozdzielczości 1920×1080 w trybie pełnoekranowym przeglądarki za każdym razem widocznych będzie tylko około 9 elementów. Dlatego nie ma potrzeby renderowania wszystkich niewidocznych węzłów i miniatur ani przenoszenia do DOM większej ilości danych zwróconych w odpowiedzi na żądanie.

Oto pomysł: po pierwszym pobraniu surowych danych z żądania API tworzymy tablicę o tej samej długości, przygotowując się do renderowania w DOM. W tablicy renderowania możemy umieścić tylko tyle danych, ile potrzeba do wypełnienia ekranu i przewinięcia do następnej pozycji. Reszta tablicy zostanie wypełniona dopiero wtedy, gdy okno wyświetlania zostanie przewinięte w jej pobliże. Nadajmy dwa indeksy do rejestrowania zakresu danych renderowania: renderingStartIndex i renderingEndIndex. Ustawiamy kursor, aby wskazać, która pozycja początkowa na liście jest widoczna. Podczas przewijania musimy stale aktualizować kursor do indeksu pierwszego widocznego elementu. Zanim animacja przewijania się zakończy, będziemy musieli sprawdzić, czy następny kursor znajduje się w tablicy danych renderowania. W zależności od rozmiaru okna karuzeli i rozmiaru kart, możemy łatwo określić, ile widocznych elementów zmieści się w oknie wyświetlania. Następnie musimy upewnić się, że elementy z bieżącego okna i następnego okna znajdują się w zakresie tablicy danych renderowania. Jeśli nie, pobieramy elementy z surowych danych, aby wypełnić pustą listę, jednocześnie usuwając dane znajdujące się przed pozycją kursora. Będzie to miało zastosowanie, gdy użytkownicy przewiną w prawo lub w lewo. Gdy użytkownicy przewijają w prawo, pobierając więcej danych w tle, uzupełniamy dane surowe za każdym razem po otrzymaniu nowych danych. Jednak dane surowe nie będą uwzględniane w renderowaniu strony.

Oto jak wygląda to po wprowadzeniu poprawek:

Profil pamięci

Przyjrzyjmy się ponownie narzędziom programistycznym Chrome. Tak jak poprzednio, pierwszy zrzut ekranu został wykonany w momencie inicjalizacji, a drugi po 12-krotnym przewinięciu w prawo. Teraz załadowanie ponad 100 elementów kosztuje jedynie 0,3 MB dodatkowej pamięci, w przeciwieństwie do 9,7 MB wcześniej.

Co dalej?

Oprócz ulepszenia komponentu karuzeli w celu obsługi dużych okien danych, podczas refaktoryzacji funkcji/strony musimy dodać więcej testów porównawczych, aby zebrać informacje o wydajności.

Chociaż nowoczesny stos aplikacji internetowych przesuwa się w kierunku front-endu, gromadzenie i ulepszanie telemetrii front-endowej jest równie ważne, jak tradycyjna telemetria back-endowa.

Ying Jiang jest głównym inżynierem oprogramowania frontendowego w Roblox. Jako pierwsza inżynierka frontendowa w Roblox, pracuje nad wprowadzeniem nowoczesnego stosu technologicznego frontendu do Roblox oraz ulepszeniem procesu tworzenia i wdrażania oprogramowania. Pracowała również nad funkcjami działającymi w czasie rzeczywistym, takimi jak czat, strumień powiadomień i komunikacja głosowa.

Ani firma Roblox Corporation, ani niniejszy blog nie promują ani nie wspierają żadnej firmy ani usługi. Ponadto nie udziela się żadnych gwarancji ani obietnic dotyczących dokładności, wiarygodności lub kompletności informacji zawartych w niniejszym blogu.