Gdy deweloper nie ogarnął wielowątkowości, parsowania JSONa i tablic.
Bo GTA Online ładowało się za wolno
Najwyraźniej znana strzelanko-ściganka, która przyniosła twórcom miliardy dolarów dochodu, jest mocno niedopracowana w kwestii wydajności. GTA Online zawsze cechowały długie czasy ładowania się. Aż w końcu niejaki t0st postanowił się temu przyjrzeć i doszedł do zaskakujących wniosków.
Najpierw sprawdził, czy ktoś już rozwiązał ten problem. Większość wyników wyszukiwania to anegdoty o tym, że gra jest po prostu tak skomplikowana, że musi się ładować tak długo, historie o tym, że architektura sieci p2p jest do bani, można też znaleźć kilka „wyszukanych” sposobów ładowania najpierw do trybu story a dopiero potem do solo session. Dodajmy do tego kilka modów, które pozwalają na pominięcie startowego wideo z logo Rockstara (producenta gry).
6 razy dłużej
Główną przyczyną frustracji graczy jest to, że GTA Online ładujące się w trybie singleplayer około minutę (co oczywiście zależy od konkretnego komputera), w trybie online potrzebuje już 6 minut aby się w pełni wczytać. Co może usprawiedliwiać dłuższy o 600% czas ładowania w trybie rozgrywki sieciowej? W grze, która swoją premierę miała ponad 7 lat temu? Na dodatek czasy ładowania oscylujące w granicach 3-15 minut zgłaszało w ankietach łącznie około 81% graczy. Tylko na topowych maszynach udawało się zejść do ok. 2 minut co wskazywało, że faktycznie chodzi tu o jakieś problemy wydajnościowe.
Szukanie przyczyny
Nasz badacz zaczął od szukania przyczyny w menedżerze zadań Windows. Zauważył, że po pierwszej minucie, w której gra wczytywała zasoby wspólne dla obu trybów rozgrywki, GTA Online zaczęło używać w maksymalnym stopniu jeden z rdzeni procesora. Gra robiła tak ponad 4 minuty. Co więcej, praktycznie nie korzystała wtedy z dysku i sieci. GPU także sobie odpoczywało, podobnie jak zużycie pamięci. Odrzuciwszy pierwsze myśli o potajmenym kopaniu kryptowaluty na komputerze gracza, t0st doszedł do wniosku iż przyczyną jest zły kod. Naprawdę zły kod.
Obliczał zamiast wczytywać
Każdy z nas spodziewałby się raczej, że wczytująca się gra powinna wymagać sporo od pamięci masowej a nie procesora. Taka struktura zużycia jaką wskazywał menedżer zadań świadczyła o jakimś poważnym błędzie dewelopera. Nasz zaintrygowany gracz odpalił deasemblera. Znalazł wpisy strlen
oraz vscan_fn
co wskazywało na parsowanie jakiegoś ciągu znaków. Był to JSON o długości 10MB, z 63 tysiącami pozycji! Przypuszczalnie był to net shop catalog zawierający wszystkie możliwe do zakupienia w sklepie GTA Online mody, przedmioty czy upgrade’y.
Okazuje się, że sscanf
odczytywał każdą pozycję, licząc pojedyncze znaki i zwracając zeskanowaną wartość. Potem przechodził jeden bajt dalej i tak przez 10MB danych.
Sprawdź oferty pracy na TeamQuest
Co więcej, od razu po przeskanowaniu danej pozycji, zostaje ona zeskładowana w tablicy. Nie ma w tym naturalnie nic złego ale to odłożenie do tablicy następuje dopiero po zeskanowaniu całej tablicy na okoliczność czy dana pozycja już się na liście znajduje. Mamy więc porównywanie hashy wszystkich pozycji co oznacza konieczność przeprowadzenia 1984531500 sprawdzeń. Czytelnicy TeamQuest już wiedzą na czym polega problem: użyto mapy zamiast hashmapy.
Co jeszcze ciekawsze – wszystkie wpisy w JSONie są unikalne. Nie było w ogóle potrzeby ich porównywania.
Feria pomyłek
Podsumowując, proces wczytywania GTA Online w trybie gry sieciowej cierpi na:
- brak obsługi wielowątkowości
- niepotrzebne parsowanie 10MB pliku JSON
- parsowanie tego JSONa w sposób wadliwy (brak hashmapy)
- błąd de-deuplikacji
A jakie jeszcze błędy mogą popełnić programiści?