Servidor FiveM con lag: encuentra el resource que lo causa
¿El servidor se congela o bajan los FPS? Distínguelo, lee el profiler de FXServer, cuenta los comandos de cada resource y encuentra el script que causa el lag.
Por Termi
- Performance
- Debugging
- Lua
En esta página
- Dos tipos de lag
- Leer el profiler del servidor
- Medir los FPS de un jugador
- La causa que ninguna de las dos herramientas muestra
- Los sospechosos habituales
- Preguntas frecuentes
- ¿Qué significa “server thread hitch warning” en FiveM?
- ¿Por qué mi servidor FiveM da hitch cada pocos segundos?
- ¿Cómo encuentro qué resource da lag a mi servidor FiveM?
- ¿Qué muestra resmon en FiveM?
- ¿Qué significa el aviso “took … ms to execute a query” de oxmysql?
- La misma búsqueda con un comando
“El servidor va con lag” son dos problemas distintos. A veces se atasca el thread del servidor y todos van a tirones a la vez; otras veces solo algunos jugadores pierden FPS mientras el servidor va bien. Esta guía muestra cómo distinguirlos, cómo leer el profiler del propio FXServer y cómo encontrar la causa que se esconde de ambos: un resource que registra miles de comandos. Al final, la misma búsqueda con un solo comando.
Dos tipos de lag
Necesitan herramientas distintas, así que primero comprueba cuál tienes: ¿hay hitch warnings, y lo notan todos o solo algunos jugadores?
Leer el profiler del servidor
FXServer trae un profiler que mide cada resource, cada thread y cada manejador de eventos. En la consola del servidor:
profiler record start
profiler record stop
profiler saveJSON lag.jsonLánzalo mientras el servidor va con lag, páralo pasados unos diez segundos y guarda la grabación. lag.json es un trace de Chrome: abre las DevTools en Chrome, ve a Performance y carga el archivo. Cada frame del servidor es un Resource Manager Tick, y dentro encuentras el tick (name) de cada resource, sus threads como thread @resource/file.lua[from..to], sus manejadores de eventos y sus exports.
Busca los frames que tardan mucho más que el resto y mira qué resource los llena. El rango de líneas te dice qué CreateThread o manejador era.
Un resource no puede iniciar el profiler por sí solo. ExecuteCommand('profiler record start') desde un script se rechaza a menos que server.cfg lo permita: add_ace resource.<name> command.profiler allow, más la misma línea para command.record y command.saveJSON.
Medir los FPS de un jugador
En el lado del jugador, F8 ofrece dos herramientas. resmon 1 muestra en vivo el tiempo de CPU y la memoria de cada resource, lo que basta cuando uno destaca claramente. Para mirar más de cerca, el mismo profiler funciona dentro del juego:
resmon 1
profiler record 500
profiler saveJSON lag.jsonEso graba 500 frames. Carga el archivo en las DevTools igual que antes y busca threads del cliente que corran en cada frame. Un bucle Wait(0) que hace trabajo real en cada frame, como medir la distancia a cientos de markers, suele ser el primer sospechoso.
La causa que ninguna de las dos herramientas muestra
Hay un tipo de lag que se esconde de ambas. Un servidor añade un pack de emotes y poco después empieza a ir con lag. El profiler no muestra ningún thread pesado, y buscar RegisterCommand en el pack encuentra un puñado de llamadas.
Las llamadas están en un bucle, tras un alias local, una por cada emote:
local register = RegisterCommand
for _, emote in ipairs(Emotes) do
register(emote.command, function() PlayEmote(emote) end, false)
TriggerEvent('chat:addSuggestion', '/' .. emote.command, emote.label)
endCon dos mil emotes, son dos mil comandos y dos mil sugerencias de chat en el juego de cada jugador. Una búsqueda de texto no puede contarlos, pero el juego sí: GetRegisteredCommands() devuelve cada comando con el resource que lo registró.
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
endEjecútalo como script de cliente y como script de servidor. Un resource con cientos de comandos merece una mirada. Uno con miles casi siempre registra un comando por cada emote o item, cuando bastaría un comando con un argumento.
Los sospechosos habituales
Preguntas frecuentes
¿Qué significa “server thread hitch warning” en FiveM?
El thread principal de FXServer debe hacer 20 ticks por segundo, uno cada 50 ms. Cuando pasan más de 150 ms entre dos ticks, la consola imprime server thread hitch warning: timer interval of 212 milliseconds, y el número es lo que duró ese hueco. Durante el hueco no corre nada más en el thread del servidor, así que todos los jugadores lo notan en el mismo momento. Algo en el servidor retuvo el thread demasiado tiempo, normalmente un resource que hace mucho trabajo en un solo frame.
¿Por qué mi servidor FiveM da hitch cada pocos segundos?
Un hitch con un ritmo regular suele venir de un thread del servidor que duerme unos segundos con Wait y luego hace mucho trabajo de golpe, como recorrer a todos los jugadores, vehículos o puntos de un job. El profiler del servidor muestra qué thread es: los frames largos nombran el resource y las líneas del thread, por ejemplo thread @jobs_garbage/server/main.lua[88..131].
¿Cómo encuentro qué resource da lag a mi servidor FiveM?
Usa el profiler integrado de FXServer. Ejecuta profiler record start en la consola del servidor, profiler record stop unos diez segundos después y luego profiler saveJSON lag.json, y carga el archivo en la pestaña Performance de las DevTools de Chrome. El tick, los threads y los manejadores de eventos de cada resource aparecen con su tiempo, así que el que está detrás de un frame largo destaca. Si solo algunos jugadores tienen lag, pídeles que escriban resmon 1 en F8 para ver en vivo el tiempo de CPU de cada resource del cliente.
¿Qué muestra resmon en FiveM?
resmon 1, escrito en la consola F8, abre el monitor de resources: una lista en vivo de cada resource del cliente con el tiempo de CPU que consume por frame y la memoria que ocupa. Mide solo el juego del jugador que lo abrió, así que explica los FPS de ese jugador y no dice nada de un hitch del servidor.
¿Qué significa el aviso “took … ms to execute a query” de oxmysql?
oxmysql imprime una línea como [10.11.6-MariaDB] jobs_garbage took 312.4512ms to execute a query!, seguida de la consulta, cada vez que una consulta tarda más que el convar mysql_slow_query_warning, 200 ms por defecto. El nombre del resource te dice qué script la envió. La consulta corre de forma asíncrona, así que por sí sola no atasca el thread del servidor, pero el script que espera el resultado llega tarde y los jugadores ven un garaje o un inventario que abre despacio. Una causa frecuente es que falte un índice en la columna de la cláusula WHERE; pon EXPLAIN delante de la consulta para ver si MySQL usa alguno.
La misma búsqueda con un comando
El agente de FiveDock hace todo esto por ti. Con las tres líneas add_ace en server.cfg, fivedock perf graba el profiler durante diez segundos, cuenta los comandos de cada resource en el servidor y en el juego de tres jugadores, y pide los FPS a cada jugador:
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.El thread del trabajo de basureros en server/main.lua:88-131 retiene el servidor unos 200 ms cada pocos segundos, y el pack de emotes tiene 2.034 comandos en el juego de los jugadores. Cuando el thread del servidor se atasca sin que nadie mire, el agente graba por su cuenta los diez segundos siguientes, así que el siguiente informe ya dice qué pasó.
Encontrar qué da lag cubre la configuración y cada parte del informe.