Optimiser un serveur FiveM

Optimiser un serveur FiveM : lire le resmon, trouver les ressources qui coûtent des ms, corriger les boucles Wait(0), alléger textures et requêtes.

En bref

  • Côté client, resmon 1 dans la console F8 affiche le temps CPU (ms) et la mémoire de chaque ressource.
  • Côté serveur, les « hitch warnings » de la console signalent un tick trop long ; profiler record 500 dit quelle ressource est en cause.
  • Une cause très courante : une boucle en Wait(0) qui tourne à chaque frame alors que le joueur est loin de tout.
  • set mysql_slow_query_warning 150 fait remonter dans la console chaque requête SQL de plus de 150 ms, avec la ressource qui l'a lancée.
  • Un dictionnaire de textures (YTD) au-delà d'environ 16 Mo de mémoire physique est le repère courant pour les problèmes de streaming.

Un serveur qui rame n'a presque jamais un seul coupable évident. La méthode ne change pas : mesurer, trouver la ressource qui coûte, la corriger ou la retirer, remesurer.

Comment savoir quelle ressource fait laguer mon serveur ?

Avec le resmon côté client et le profiler côté serveur. Le resmon (moniteur de ressources) affiche, pour chaque ressource qui tourne sur ton client, son temps CPU en millisecondes et sa mémoire.

Comment ouvrir le resmon ?

Ouvre la console avec F8 et tape :

resmon 1

Si le client répond Access denied for command resmon, les commandes de développement sont bloquées : la doc des commandes client indique de lancer FiveM avec l'argument +set moo 31337.

Comment lire le resmon ?

En comparant les ressources entre elles et selon l'endroit où tu es, pas en visant un chiffre magique :

  • Regarde les ressources au repos. Une ressource qui n'a rien à faire à cet instant (un garage alors que tu es à l'autre bout de la carte) devrait être quasiment à zéro.
  • Teste à plusieurs endroits : en ville, dans un intérieur chargé, en véhicule, près d'un job.
  • Une valeur haute pendant l'usage est normale. La même valeur en permanence ne l'est pas.

Comment trouver ce qui bloque côté serveur ?

En lisant les hitch warnings puis en lançant le profiler. Un hitch warning dans la console serveur signale qu'un tick a pris trop de temps. La fiche technique Cfx.re cite deux causes fréquentes : des requêtes SQL trop longues et des boucles mal optimisées qui bloquent l'exécution.

Le profiler marche côté client (F8) comme côté serveur (console du serveur) :

profiler record 500
profiler status
profiler saveJSON profil.json

500 frames est la valeur de départ conseillée par la doc. profiler view ouvre le résultat ; côté serveur, copie le lien affiché dans Google Chrome. Le fichier JSON s'ouvre aussi dans Chrome : F12, onglet Performance, puis charger le profil. Tu vois frame par frame quelle ressource et quelle fonction prennent le temps.

Pourquoi Wait(0) fait-il chuter les performances ?

Parce que Wait(0) reprend la boucle à la frame suivante, donc des dizaines de fois par seconde, même quand il n'y a rien à faire :

-- À éviter : vérifie la distance à chaque frame, même à l'autre bout de la carte
CreateThread(function()
    while true do
        Wait(0)
        local coords = GetEntityCoords(PlayerPedId())
        if #(coords - vec3(25.7, -1347.3, 29.5)) < 2.0 then
            -- afficher l'aide, dessiner un marker...
        end
    end
end)

Wait(0) est nécessaire pour dessiner un marker ou lire une touche, pas pour savoir si le joueur est loin. On adapte l'attente à la distance :

local shop = vec3(25.7, -1347.3, 29.5)

CreateThread(function()
    while true do
        local sleep = 1000
        local dist = #(GetEntityCoords(PlayerPedId()) - shop)

        if dist < 15.0 then
            sleep = 0
            -- ici seulement : marker, texte d'aide, lecture de touche
        end

        Wait(sleep)
    end
end)

Avec ox_lib, lib.points fait ce travail et ne réveille ton code que près du point :

local point = lib.points.new({
    coords = vec3(25.7, -1347.3, 29.5),
    distance = 15,
})

function point:nearby()
    -- appelé à chaque frame, uniquement dans le rayon
    if self.currentDistance < 2.0 then
        -- afficher l'aide
    end
end

Les autres réflexes :

  • Réagis à un event au lieu de vérifier en boucle une valeur qui change rarement (job, argent).
  • Sors de la boucle ce qui ne change pas : coordonnées fixes, config, hashes de modèles.
  • Côté serveur, pas de boucle courte sur tous les joueurs. Une sauvegarde toutes les quelques minutes suffit.
  • Une seule ressource par fonction. Deux HUD ou deux systèmes de carburant coûtent double pour rien.

Comment accélérer la base de données ?

En trouvant les requêtes lentes, puis en ajoutant les index qui manquent. Sur ESX Legacy et Qbox, c'est oxmysql qui parle à la base ; il remplace mysql-async et ghmattimysql, garde-en un seul.

set mysql_slow_query_warning 150

Chaque requête plus lente que ce seuil (en ms) est signalée dans la console avec le nom de la ressource, sa durée et la requête elle-même. Les causes habituelles :

  • Pas d'index sur la colonne filtrée. EXPLAIN te dit si MariaDB parcourt toute la table :
EXPLAIN SELECT * FROM player_logs WHERE identifier = 'license:xxxx';
-- si toute la table est parcourue :
ALTER TABLE player_logs ADD INDEX idx_identifier (identifier);
  • Des tables de logs qui grossissent sans fin. Purge ou archive ce qui est ancien.
  • Un SELECT puis un INSERT ou un UPDATE là où un INSERT ... ON DUPLICATE KEY UPDATE suffit, comme le recommande la doc d'oxmysql.
  • Des sauvegardes trop fréquentes de chaque joueur, inventaire ou véhicule.

Pourquoi les textures ne chargent-elles pas ?

Presque toujours à cause d'assets trop lourds. Textures absentes, bâtiments qui apparaissent tard, voitures invisibles : ce « lag » n'est pas du CPU, c'est du streaming.

Quand une ressource démarre, le serveur signale dans sa console ses assets surdimensionnés, avec la mémoire qu'ils occupent, et prévient qu'ils peuvent causer des problèmes de streaming. Le repère couramment retenu est 16 Mo de mémoire physique par YTD.

  • Réduis la résolution. Une texture 4096 x 4096 passée en 2048 x 2048 occupe quatre fois moins de mémoire dans le même format.
  • Utilise des formats compressés (DXT) avec des mipmaps.
  • Trie tes packs de véhicules et de vêtements : chaque addon streamé alourdit la connexion et le budget mémoire.
  • Regarde le streaming en direct avec la commande client strdbg.

Pour remplacer une ressource par sa version allégée sans casser l'ordre de démarrage, suis Installer une ressource.

Questions fréquentes

Combien de ms est acceptable pour une ressource ?

Il n'y a pas de seuil officiel. Une ressource qui n'a rien à faire devrait être proche de zéro ; celle qui reste haute en permanence, loin de tout, est à ouvrir en priorité.

Pourquoi resmon affiche « Access denied » ?

Parce que c'est une commande de développement. Lance FiveM avec l'argument +set moo 31337, comme l'indique la doc Cfx.re.

Une machine plus puissante règle-t-elle le lag ?

Pas celui des scripts client : une boucle mal écrite côté client tourne sur le PC de chaque joueur, pas sur ton serveur. Côté serveur, une requête lente reste lente tant qu'il manque un index.

Quelle taille maximum pour un fichier YTD ?

Il n'y a pas de limite stricte, mais 16 Mo de mémoire physique par dictionnaire est le repère courant. Au-delà, le risque de textures qui ne chargent pas augmente.

Faut-il garder mysql-async avec oxmysql ?

Non. oxmysql prend en charge les appels écrits pour mysql-async et ghmattimysql. Garder deux connecteurs n'apporte rien et complique le diagnostic.

Besoin d'un coup de main ?

Si tu as mesuré sans trouver, ou si tu n'as pas le temps de reprendre chaque ressource, KAAPSULE, studio FiveM francophone, fait l'audit complet (resmon, profiler, base, streaming) avec les corrections : c'est la prestation Optimisation. Si le lag vient avec des comportements bizarres, lis aussi Backdoor FiveM. Pour une question rapide, le Discord KAAPSULE est ouvert.