Jak znaleźć zasób, przez który laguje serwer FiveM
Przycięcia serwera czy niski FPS? Jak je odróżnić, czytać profiler FXServera, liczyć komendy zasobów i znaleźć skrypt, który stoi za lagiem.
Autor: Termi
- Performance
- Debugging
- Lua
Na tej stronie
- Dwa rodzaje laga
- Czytaj profiler serwera
- Zmierz FPS gracza
- Przyczyna, której nie pokaże żadne z nich
- Zwykli podejrzani
- Częste pytania
- Co znaczy „server thread hitch warning” w FiveM?
- Dlaczego serwer FiveM przycina co kilka sekund?
- Jak znaleźć zasób, który laguje serwer FiveM?
- Co pokazuje resmon w FiveM?
- Co znaczy ostrzeżenie oxmysql „took … ms to execute a query”?
- To samo polowanie jedną komendą
„Serwer laguje” to dwa różne problemy. Czasem staje wątek serwera i przycina wszystkich naraz, a czasem część graczy traci FPS, choć serwer ma się dobrze. Ten poradnik pokazuje, jak je odróżnić, jak czytać wbudowany profiler FXServera i jak znaleźć przyczynę, która chowa się przed oboma narzędziami: zasób rejestrujący tysiące komend. Na końcu to samo polowanie jedną komendą.
Dwa rodzaje laga
Każdy wymaga innych narzędzi, więc najpierw sprawdź, który masz: czy w konsoli są hitch warningi i czy czują to wszyscy, czy tylko część graczy?
Czytaj profiler serwera
FXServer ma wbudowany profiler, który mierzy czas każdego zasobu, wątku i handlera eventów. W konsoli serwera:
profiler record start
profiler record stop
profiler saveJSON lag.jsonUruchom go, kiedy serwer laguje, zatrzymaj po mniej więcej dziesięciu sekundach i zapisz nagranie. lag.json to trace Chrome’a: otwórz DevTools w Chrome, przejdź do Performance i wczytaj plik. Każda klatka serwera to Resource Manager Tick, a w niej tick (nazwa) każdego zasobu, jego wątki jako thread @zasób/plik.lua[od..do], handlery eventów i eksporty.
Szukaj klatek, które trwają dużo dłużej niż reszta, i sprawdź, który zasób je wypełnia. Zakres linii mówi, który CreateThread albo handler to był.
Zasób nie uruchomi profilera sam. ExecuteCommand('profiler record start') ze skryptu zostanie odrzucone, chyba że pozwala na to server.cfg: add_ace resource.<nazwa> command.profiler allow i ta sama linijka dla command.record oraz command.saveJSON.
Zmierz FPS gracza
Po stronie gracza F8 ma dwa narzędzia. resmon 1 pokazuje na żywo czas CPU i pamięć każdego zasobu, co wystarcza, gdy jeden zasób wyraźnie odstaje. Żeby przyjrzeć się dokładniej, ten sam profiler działa w grze:
resmon 1
profiler record 500
profiler saveJSON lag.jsonTo nagrywa 500 klatek. Wczytaj plik w DevTools tak samo i szukaj wątków klienta, które działają co klatkę. Pętla z Wait(0), która w każdej klatce robi prawdziwą pracę, np. liczy odległość do setek markerów, to zwykle pierwszy podejrzany.
Przyczyna, której nie pokaże żadne z nich
Jeden rodzaj laga chowa się przed oboma narzędziami. Serwer dodaje paczkę emotek i wkrótce zaczyna lagować. Profiler nie pokazuje żadnego ciężkiego wątku, a szukanie RegisterCommand w paczce znajduje kilka wywołań.
Wywołania siedzą w pętli, za lokalnym aliasem, po jednym na każdą emotkę:
local register = RegisterCommand
for _, emote in ipairs(Emotes) do
register(emote.command, function() PlayEmote(emote) end, false)
TriggerEvent('chat:addSuggestion', '/' .. emote.command, emote.label)
endPrzy dwóch tysiącach emotek to dwa tysiące komend i dwa tysiące podpowiedzi czatu w grze każdego gracza. Wyszukiwanie tekstu ich nie policzy, ale gra tak: GetRegisteredCommands() zwraca każdą komendę razem z zasobem, który ją zarejestrował.
local counts = {}
for _, command in ipairs(GetRegisteredCommands()) do
counts[command.resource] = (counts[command.resource] or 0) + 1
end
for resource, count in pairs(counts) do
if count > 100 then print(resource, count) end
endUruchom to jako skrypt klienta i jako skrypt serwera. Zasób z setkami komend warto obejrzeć. Ten z tysiącami prawie zawsze rejestruje komendę na każdą emotkę albo przedmiot, choć wystarczyłaby jedna komenda z argumentem.
Zwykli podejrzani
Częste pytania
Co znaczy „server thread hitch warning” w FiveM?
Główny wątek FXServera ma tykać 20 razy na sekundę, czyli co 50 ms. Kiedy między dwoma tickami minie ponad 150 ms, konsola wypisuje server thread hitch warning: timer interval of 212 milliseconds, a liczba to długość tej przerwy. Przez ten czas nic innego na wątku serwera nie działa, więc przycina wszystkich graczy naraz. Coś na serwerze trzymało wątek za długo, zwykle jeden zasób, który robi dużo pracy w jednej klatce.
Dlaczego serwer FiveM przycina co kilka sekund?
Przycięcie, które wraca w równych odstępach, zwykle robi wątek serwera, który śpi kilka sekund na Wait, a potem za jednym zamachem wykonuje ciężką robotę, np. przechodzi po wszystkich graczach, pojazdach albo punktach pracy. Profiler serwera pokaże, który to wątek: długie klatki podają zasób i linie wątku, np. thread @jobs_garbage/server/main.lua[88..131].
Jak znaleźć zasób, który laguje serwer FiveM?
Użyj wbudowanego profilera FXServera. Wpisz w konsoli serwera profiler record start, po mniej więcej dziesięciu sekundach profiler record stop, potem profiler saveJSON lag.json i wczytaj plik w zakładce Performance w DevTools Chrome’a. Każdy tick zasobu, wątek i handler eventu ma tam swój czas, więc zasób stojący za długą klatką od razu widać. Jeśli laguje tylko część graczy, niech wpiszą w F8 resmon 1, żeby na żywo zobaczyć czas CPU każdego zasobu po stronie klienta.
Co pokazuje resmon w FiveM?
resmon 1 wpisane w konsoli F8 otwiera monitor zasobów: listę wszystkich zasobów klienta na żywo, z czasem CPU, który zajmują w każdej klatce, i pamięcią, którą trzymają. Mierzy tylko grę gracza, który go otworzył, więc tłumaczy jego FPS i nic nie mówi o przycięciach serwera.
Co znaczy ostrzeżenie oxmysql „took … ms to execute a query”?
oxmysql wypisuje linijkę w rodzaju [10.11.6-MariaDB] jobs_garbage took 312.4512ms to execute a query!, a pod nią samo zapytanie, za każdym razem, gdy zapytanie trwa dłużej niż convar mysql_slow_query_warning, domyślnie 200 ms. Nazwa zasobu mówi, który skrypt je wysłał. Zapytanie idzie asynchronicznie, więc samo nie zatrzymuje wątku serwera, ale skrypt, który czeka na wynik, się spóźnia i gracze widzą garaż albo ekwipunek otwierający się z opóźnieniem. Częsta przyczyna to brak indeksu na kolumnie z WHERE; dopisz EXPLAIN przed zapytaniem, żeby sprawdzić, czy MySQL jakiegoś używa.
To samo polowanie jedną komendą
Agent FiveDocka robi to wszystko za ciebie. Z trzema linijkami add_ace w server.cfg komenda fivedock perf nagrywa profiler przez dziesięć sekund, liczy komendy każdego zasobu na serwerze i w grze trzech graczy, i pyta każdego gracza o FPS:
my-city profiled 10 s · 214 players online
server thread late by 3.8 ms on average, 212 ms at worst in the last minute
Server 198 ticks, the slowest took 212 ms
resource total per tick worst tick
jobs_garbage 1,236 ms 6.2 ms 205 ms
hud 412 ms 2.1 ms 6.3 ms
oxmysql 96 ms 0.5 ms 14 ms
emotes 12 ms 0.1 ms 0.4 ms
Where exactly the threads, events and exports that took longest
jobs_garbage 611 ms thread · server/main.lua:88-131 · 3× · worst 203 ms
jobs_garbage 598 ms thread · server/main.lua:12-40 · 198× · worst 6.1 ms
hud 380 ms event hud:sync · server.lua:52-77 · 1,420× · worst 4.2 ms
oxmysql 88 ms export · dist/build.js:310 · 402× · worst 14 ms
Commands on the server, and in the game of 3 sampled players
resource server players
emotes – 2,034
admin_menu 61 12
hud 9 4
total 248 2,310
A command per emote or item adds up fast. Check whether that resource needs them all.Wątek śmieciarza w server/main.lua:88-131 co kilka sekund zatrzymuje serwer na około 200 ms, a paczka emotek ma w grze graczy 2034 komendy. Kiedy wątek serwera stanie, a nikt nie patrzy, agent sam nagrywa kolejne dziesięć sekund, więc następny raport już mówi, co się stało.
Znajdź, co laguje opisuje konfigurację i każdą część raportu.