Serveur Minecraft qui lag : trouver et corriger les causes
Est-ce le serveur qui lag ou la connexion ? Les deux donnent la même impression, mais les causes n'ont rien à voir. Mesurer avec les TPS et Spark, prégénérer les chunks, trouver le coupable.
« Le serveur lag » est le message le plus fréquent dans le système de tickets de tout exploitant de serveur de jeu, et en même temps le plus inutilisable. Derrière cette seule phrase se cachent au moins trois problèmes techniques totalement différents, qui n'ont rien à voir les uns avec les autres et qui se corrigent par des moyens tout aussi différents. Celui qui devine au lieu de mesurer passe des semaines à tripoter view-distance et les flags Java, alors que la vraie cause est une chaîne de hoppers cassée dans la cave d'un joueur.
Cet article suit l'ordre dans lequel la démarche fonctionne : d'abord la distinction, puis la mesure, puis la cause, puis la contre-mesure. Et à la fin, la question que la plupart des guides laissent de côté : à quoi reconnaissez-vous que le problème est réellement réglé ?
Deux symptômes qui donnent exactement la même impression
Il existe deux types de saccades fondamentalement différents, plus un troisième cas qui n'a rien à voir avec le serveur.
Le lag serveur signifie ceci : le serveur n'arrive plus à tenir ses 20 étapes de calcul par seconde. Le monde lui-même tourne au ralenti. Les mobs restent figés ou tressautent, les fours mettent plus longtemps, les blocs cassés réapparaissent, les porte-armures flottent avec du retard.
Le lag réseau signifie ceci : le serveur calcule parfaitement, mais les paquets entre le joueur et le serveur mettent trop de temps ou se perdent. Le joueur est tiré en arrière quand il court (rubberbanding), les coups ne portent pas, le chat arrive en retard, mais les mobs alentour se déplacent tout à fait normalement.
Le lag client est le troisième cas : trop peu d'images par seconde sur la machine du joueur, le plus souvent à cause des shaders, d'une distance d'affichage trop élevée côté client ou d'une quantité de RAM allouée insuffisante. C'est invisible depuis le serveur et cela ne s'y corrige pas non plus.
| Observation | Lag serveur | Lag réseau |
|---|---|---|
| Qui est touché | tous les joueurs en même temps | quelques joueurs isolés, souvent d'une même région |
| Mobs à proximité | tressautent, restent figés, se téléportent | se déplacent normalement |
| Ping dans le menu Tab | normal | élevé ou instable |
| Console | « Can't keep up! » | calme, éventuellement des timeouts |
| Mesure des TPS | sous 20 | exactement 20 |
| Moment | reproductible sous charge | souvent le soir, selon l'heure de la journée |
La règle qui se vérifie presque toujours : si tout le monde est touché en même temps, c'est le serveur. Si seuls quelques joueurs le sont, c'est la ligne. Un cas particulier casse cette règle : un serveur totalement surchargé confirme aussi les paquets réseau trop tard et génère alors, en plus, des pings élevés. C'est pourquoi on mesure toujours les deux.
Le premier test prend 60 secondes
Connectez-vous au serveur en SSH et ouvrez la console du serveur. Si le service ne tourne pas encore proprement en arrière-plan, l'article Démarrer un serveur Minecraft automatiquement vous aidera.
Sur Paper, Purpur et Folia à partir de la 1.21, le profileur Spark est déjà contenu dans le serveur, il n'y a rien à installer. Dans le jeu ou dans la console :
spark tps
spark health --memory --network
La sortie de spark tps affiche quatre fenêtres de temps (5 secondes, 1, 5 et 15 minutes) ainsi que les durées de tick sous forme de minimum, médiane, 95e percentile et maximum.
Sur du Vanilla pur, sans plugins, il existe /tick query. La commande renvoie la cadence cible et le temps de tick moyen. En complément, F3 plus 2 affiche un graphique des ticks pour les opérateurs.
La console trahit souvent le problème d'elle-même. Ce sont typiquement ces lignes, au mot près, que les lecteurs recherchent :
[Server thread/WARN]: Can't keep up! Is the server overloaded? Running 2123ms or 42 ticks behind
[Server thread/WARN]: Can't keep up! Did the system time change, or is the server overloaded? Running 2340ms behind
Ce message veut simplement dire que le serveur a mis nettement plus de temps que les 50 millisecondes autorisées pour une étape de calcul et qu'il doit sauter des ticks. Un message isolé après un redémarrage ou une génération de monde est normal. Un message toutes les quelques minutes est un vrai problème.
En parallèle, vérifiez le côté système. mpstat ne fait partie de l'équipement de base d'aucun des systèmes testés, il vient du paquet sysstat et doit être installé une fois pour toutes :
apt-get install -y sysstat procps
uptime
free -h
mpstat 1 3
Sur AlmaLinux, Rocky Linux et Oracle Linux, la première ligne devient dnf -y install sysstat procps-ng iproute : là-bas, le paquet qui contient free, uptime, top et vmstat ne s'appelle pas procps mais procps-ng.
Dans la sortie de mpstat, c'est surtout la colonne %steal qui est intéressante. Des valeurs durablement supérieures à 5 pour cent signifient que la machine virtuelle attend du temps CPU occupé par un autre invité. Ce n'est alors pas un problème Minecraft, mais un problème de capacité du matériel sous-jacent.
Une réserve à propos de ces trois commandes : sur un serveur qui vous appartient ou sur un VPS, elles montrent exactement ce que vous voulez savoir. En revanche, si votre serveur tourne dans un conteneur (container), par exemple dans un panel de jeu comme Pterodactyl, free, uptime, vmstat et mpstat remontent les valeurs du système hôte et non celles de votre instance. Vous voyez alors une charge et une mémoire qui ne sont pas les vôtres. Dans ce cas, fiez-vous à l'affichage du panel et à spark health.
Lire correctement les TPS et le MSPT
Un serveur Minecraft calcule 20 ticks par seconde, chaque tick dispose donc d'un budget de 50 millisecondes. Le MSPT (millisecondes par tick) est la valeur la plus parlante, car il révèle les problèmes avant même que les TPS ne chutent. Un serveur à 20,0 TPS et 46 ms de MSPT tourne à la limite absolue et bascule dès que le prochain joueur entre dans une nouvelle zone.
- MSPT sous 30 ms : sain, il reste de la marge.
- MSPT de 30 à 45 ms : serré, mais jouable. Agissez dès maintenant.
- MSPT au-dessus de 50 ms : les TPS chutent forcément, les joueurs le remarquent.
La répartition compte plus que la moyenne. Une médiane à 18 ms avec un maximum à 900 ms signale des pics : des événements ponctuels coûteux comme la sauvegarde automatique, la génération de chunks ou une tâche de plugin qui revient chaque minute. Une médiane à 60 ms signale au contraire une charge permanente, donc trop de contenu tické pour la puissance de calcul disponible. Les contre-mesures sont totalement différentes.
Un point que les conseillers en matériel passent volontiers sous silence : le tick principal de Minecraft s'exécute dans un seul thread. Le chargement des chunks et le réseau sont déportés, mais pas la simulation du monde elle-même. Un serveur avec 32 cœurs et une faible performance par cœur est plus lent pour Minecraft qu'un serveur avec 8 cœurs rapides. Les cœurs supplémentaires ne servent que lorsque plusieurs instances de serveur tournent dessus.
Spark : du soupçon à la preuve
Timings, l'outil standard pendant des années, est passé en mode inactif chez Paper depuis la série 1.21 et ne fournit plus de données exploitables. Publier aujourd'hui un lien Timings revient à ne rien mesurer. Le successeur s'appelle Spark : il est intégré à Paper, disponible en mod pour Fabric, Forge et NeoForge, et en version distincte pour Velocity et BungeeCord.
La démarche décisive : profilez pendant que le problème se produit. Un profil pris sur un serveur vide à trois heures du matin ne vaut rien.
spark profiler start --timeout 300
spark profiler stop
Pour les pics qui ne surviennent qu'occasionnellement, on isole directement les mauvais ticks :
spark profiler start --only-ticks-over 60 --timeout 600
Seuls les ticks ayant duré plus de 60 millisecondes sont alors enregistrés. Ce sont exactement ceux que les joueurs ressentent. Le reste est ignoré et ne vient pas brouiller l'image.
À la lecture du flame graph, les débutants font presque toujours la même erreur : ils regardent la ramification la plus profonde. Ce qu'il faut regarder, c'est la largeur des barres situées juste sous le tick serveur. Une entrée à 3 pour cent n'a aucune importance, même si elle descend sur cent niveaux. Règle empirique : un plugin qui dépasse à lui seul 15 pour cent du temps de tick est un candidat. Des entrées très larges autour des entités de bloc pointent vers la redstone et les hoppers, des entrées larges autour du chargement des chunks vers la génération de monde.
Une remarque sur la confidentialité : le rapport envoyé est accessible publiquement via son lien et contient des informations système, des chemins, des paramètres de démarrage et la liste complète des plugins. Ne transmettez ce lien qu'à des personnes à qui vous confieriez ces informations. Avec --save-to-file, le profil reste en local.
Les coupables habituels
Redstone et fermes
Les hoppers sont de loin les blocs les plus coûteux du jeu, parce que chacun d'eux vérifie à chaque tick si quelque chose se trouve au-dessus de lui. Un système de tri avec 400 hoppers coûte plus de temps de calcul que cent mobs. S'y ajoutent les horloges à observers, qui tournent même quand personne ne se trouve à proximité, dès lors que le chunk est simulé. Si Spark passe étonnamment beaucoup de temps dans les entités de bloc, cherchez précisément ce genre d'installations.
Entités
Sur Paper, /paper entity list répertorie les entités par monde et par type, avec les coordonnées de chunk. C'est le chemin le plus rapide vers la zone problématique. Trouvailles typiques : plusieurs milliers de piles d'objets dans une ferme à mobs, un enclos d'élevage avec 300 vaches, une zone oubliée pleine de flèches abandonnées au sol.
Contre-mesures utiles dans spigot.yml : baisser l'entity-activation-range pour les animaux et les monstres (par exemple les animaux de 32 à 16, les monstres de 32 à 24) et augmenter légèrement le merge-radius pour les objets et les orbes d'expérience, afin qu'il existe moins d'objets isolés. Dans paper-world-defaults.yml, entity-per-chunk-save-limit limite le nombre d'objets d'un même type qui sont sauvegardés par chunk.
Chargement des chunks
Un joueur en elytra ou sur un cheval rapide oblige le serveur à générer en permanence du nouveau terrain. La génération de monde est l'opération unitaire la plus coûteuse qui soit. La même chose se produit lors de la première entrée dans le Nether ou après un agrandissement de la worldborder. La solution n'est pas une valeur de configuration mais la prégénération, et elle mérite bien la section qui lui est consacrée plus bas.
Plugins
Quand Spark désigne un plugin, l'affaire est entendue. Sinon, seule la recherche par dichotomie aide : désactiver la moitié des plugins, mesurer, puis continuer à couper en deux la moitié incriminée. Avec 32 plugins, cela fait cinq redémarrages au lieu de 32. Faites impérativement une sauvegarde avant, car les plugins qui écrivent des données de monde peuvent laisser derrière eux, une fois retirés, des contenus qui ne fonctionnent plus sans eux.
Prégénérer les chunks avant que les joueurs n'y marchent
C'est la mesure isolée la plus efficace de tout cet article, et c'est la plus souvent oubliée. La raison tient à la façon dont Minecraft travaille : charger depuis le disque un chunk déjà généré ne coûte presque rien. Générer un nouveau chunk implique en revanche carte des hauteurs, biomes, répartition des minerais, grottes, structures et calcul de la lumière, et une grande partie de tout cela s'exécute dans le thread principal. Exactement là où doivent aussi naître les 20 ticks par seconde.
C'est pourquoi ça saccade typiquement au moment où quelqu'un s'envole en elytra ou construit une voie ferrée vers nulle part : le serveur génère du monde alors qu'il doit en même temps calculer le jeu. En générant une fois le monde à l'avance jusqu'à la bordure, vous transformez un calcul coûteux en une simple lecture disque, bien meilleur marché.
Chunky, l'outil de référence
Chunky est le prégénérateur couramment utilisé aujourd'hui : il tourne comme plugin sur Paper, Spigot et Purpur, et comme mod sur Fabric et Forge. La procédure est la même sur toutes les plateformes :
/chunky world world
/chunky center 0 0
/chunky radius 5000
/chunky start
Le rayon est exprimé en blocs et doit correspondre à la bordure du monde. Chunky signale de lui-même la progression et la durée restante estimée ; avec /chunky pause et /chunky continue, le traitement peut être interrompu et repris à tout moment, y compris par-delà un redémarrage.
Le Nether et l'End sont des mondes distincts et doivent être prégénérés séparément. Sur Paper et Spigot, ils portent par défaut ces noms :
/chunky world world_nether
/chunky radius 1000
/chunky start
Pour le Nether, un rayon plus petit suffit, car un bloc y correspond à huit blocs dans le monde principal. Un rayon Nether de 1000 couvre donc 8000 blocs du monde principal.
Ce que vous devez prévoir
- Le temps. Un rayon de 5000 blocs représente environ 78 millions de blocs de surface. Selon le matériel, le modpack et le générateur de monde, cela prend d'une heure à plusieurs jours. Les modpacks dotés de leur propre générateur de monde sont nettement plus lents que le Vanilla.
- L'espace de stockage. Un monde prégénéré occupe vite plusieurs gigaoctets. Vérifiez au préalable ce qu'il reste de libre, sinon le disque se remplit pendant le traitement, et cela touche le serveur bien plus durement que n'importe quelle saccade. Pour savoir comment le vérifier et faire le ménage, lisez Disque plein : trouver et libérer de l'espace.
- Le moment. Prégénérez avec un serveur vide, pas en pleine exploitation. Pendant le traitement, la cadence de tick est mauvaise, comme prévu, ce n'est pas un défaut. Tout l'intérêt de l'opération est justement de sortir cette charge du temps de jeu.
- Définir la bordure du monde. Sans bordure, quelqu'un finira par sortir de la zone prégénérée et tout recommence. Fixez la bordure au rayon que vous avez prégénéré.
Faire le ménage après coup
Si le monde a déjà grandi et contient des zones où plus personne ne se rend, Chunky supprime les chunks situés au-delà de la bordure du monde :
/chunky trim
Cela réduit sensiblement le monde et donc aussi les sauvegardes. Créez impérativement une sauvegarde avant, car les chunks supprimés sont régénérés à la prochaine visite et tout ce que les joueurs y avaient construit est perdu.
Si Chunky n'entre pas en ligne de compte
Sur les serveurs plus anciens, on trouve encore souvent WorldBorder avec /wb fill. Cela remplit le même office, mais le projet n'est presque plus maintenu depuis des années, et pour les versions de serveur actuelles, Chunky est le choix le plus fiable. Dans les deux cas, vérifiez avant l'installation que la version proposée correspond réellement à celle de votre serveur.
view-distance et simulation-distance
Ces deux valeurs de server.properties sont sans cesse confondues.
view-distancedétermine jusqu'où les chunks sont envoyés au client. Coûte de la bande passante et un peu de mémoire.simulation-distancedétermine jusqu'où le serveur calcule les entités, la redstone et les mises à jour de blocs. Coûte du temps CPU dans le tick principal.
Les chunks situés entre la limite de simulation et la limite d'affichage restent visibles, mais sont gelés côté serveur. Le coût croît de façon quadratique : avec view-distance=10, cela fait 21 fois 21, soit 441 chunks par joueur.
Valeurs de départ éprouvées pour un réseau survie de 10 à 30 joueurs :
view-distance=8
simulation-distance=5
Si vous tombez encore sur des guides mentionnant no-tick-view-distance : cette option Paper est dépassée. Mojang a introduit simulation-distance avec la 1.18 et a ainsi résolu officiellement le même problème. Définir aujourd'hui l'ancienne valeur ne produit aucun effet.
Le prix des valeurs basses est rarement mentionné : en dessous de 4 pour simulation-distance, les fermes AFK s'effondrent, les apparitions de mobs se comportent autrement, les fours du chunk voisin cessent de tourner et les horloges de redstone s'arrêtent. Si votre communauté vit beaucoup de ses fermes, vous économisez ici au mauvais endroit et échangez un problème technique contre un problème de joueurs. Procédez par pas d'une unité et mesurez après chaque étape.
Faire le ménage sans détruire le monde
Toute intervention sur les données du monde commence par une sauvegarde, serveur arrêté. Aucun compromis, aucune exception :
tar -czf sauvegarde-monde.tar.gz world world_nether world_the_end
Ensuite, il vaut la peine de regarder la taille des données de région :
du -sh world/region
Les mondes qui ont grandi pendant des années contiennent souvent des centaines de mégaoctets de terrain qu'un seul joueur a survolé une fois. Ces chunks ne coûtent pas de temps de tick, mais de l'espace disque, et ils allongent chaque sauvegarde. Si la place vient à manquer, l'article Disque plein sous Linux : faire le ménage apporte un complément.
Des pics réguliers de l'ordre de la seconde, qui surviennent exactement toutes les cinq minutes, sont presque toujours la sauvegarde automatique. Dans bukkit.yml, ticks-per.autosave pilote l'intervalle ; dans paper-world-defaults.yml, max-auto-save-chunks-per-tick limite ce qui est écrit par tick. Une valeur plus faible répartit la charge au lieu de la concentrer.
Pour les petits serveurs privés, server.properties propose depuis la série 1.21 l'option pause-when-empty-seconds. Si la valeur qui s'y trouve est supérieure à zéro, le serveur cesse de ticker le monde après ce délai sans joueur. Sur un serveur root partagé, cela économise sensiblement du temps de calcul.
Quand la JVM freine
Si le temps de tick reste bas en moyenne mais grimpe irrégulièrement à plusieurs centaines de millisecondes, c'est souvent le ramasse-miettes de l'environnement d'exécution Java qui est en cause. Cela se vérifie directement :
spark gcmonitor
spark heapsummary
Deux idées reçues très répandues : plus de heap n'est pas automatiquement mieux, car les gros heaps produisent des pauses plus longues lors du nettoyage. Et le heap ne doit jamais être choisi si grand que le système d'exploitation se retrouve poussé dans le swap. Un serveur Minecraft qui swappe est irrémédiablement lent. Vérifiez-le avec vmstat 1 5 : des valeurs permanentes dans les colonnes si et so sont une condamnation à mort. Le contexte est expliqué dans l'article Configurer le swap et éviter les erreurs Out of Memory.
Ce message est un symptôme, pas une cause :
java.lang.OutOfMemoryError: Java heap space
Augmenter le heap ne fait que repousser le crash si un plugin fuit en mémoire ou si des millions d'entités existent.
Pour la version de Java, les distributions diffèrent nettement, et c'est précisément là que beaucoup d'installations échouent. À partir de Minecraft 1.20.5, Java 21 est exigé. Debian 12 ne fournit dans son dépôt standard qu'OpenJDK 17 et pas OpenJDK 21 ; Debian 13 fournit 21 et 25, mais pas 17. Ubuntu 22.04 et 24.04 ont 17 et 21 dans leur dépôt. Si vous devez rester sur Debian 12, installez Temurin depuis le dépôt Adoptium. Les étapes sont décrites dans Installer Java 21 sur Debian, et pour les versions de serveur plus anciennes dans Installer Java 17 sur Debian.
N'attrapez pas au passage le commode paquet fourre-tout default-jre-headless. Selon la version de la distribution, il pointe vers une version totalement différente : Debian 13 et Ubuntu 24.04 livrent ainsi Java 21, Debian 12 livre Java 17, Debian 11 et Ubuntu 22.04 livrent Java 11. L'installation se déroule partout sans erreur, mais sur les deux dernières le serveur ne démarre malgré tout pas. Nommez donc la version explicitement, c'est-à-dire openjdk-21-jre-headless.
java -version
java -XX:+PrintFlagsFinal -version 2>/dev/null | grep -w MaxHeapSize
Le 2>/dev/null supprime la bannière de version que la JVM écrit sur la sortie d'erreur et qui se retrouverait sinon au milieu du résultat. Et grep -w MaxHeapSize renvoie exactement une ligne, alors que la recherche approximative trouve en plus SoftMaxHeapSize.
Quand ça tourne mal et comment revenir en arrière
Le serveur s'interrompt sur une erreur watchdog. Le log indique alors en substance qu'un seul tick a duré 60 secondes et que le serveur est considéré comme planté. Ce n'est pas un dysfonctionnement mais une mesure de protection contre un processus durablement bloqué. La stacktrace jointe vaut de l'or : elle montre exactement où le serveur était coincé. La valeur max-tick-time dans server.properties pilote ce seuil. La désactiver ne corrige rien, cela transforme simplement le crash en un serveur définitivement gelé.
Après une modification de configuration, c'est pire. C'est exactement pour cela que s'applique la règle la plus importante de ce diagnostic : une seule modification par mesure, et notez la valeur de départ. Si vous touchez en même temps à view-distance, aux entity ranges et aux flags Java, vous ne saurez pas ensuite ce qui a agi.
Le serveur ne démarre plus après le crash. Le plus souvent, level.dat est endommagé. Le dossier du monde contient level.dat_old, que vous pouvez copier par-dessus après avoir mis de côté une copie de l'état cassé. Pour des fichiers de région endommagés, seule la sauvegarde aide.
Tout est optimisé et ça saccade toujours. Vérifiez alors la couche du dessous : %steal dans mpstat, la pagination dans vmstat et la latence disque. Si le temps de tick reste élevé alors que Spark ne montre aucun responsable isolé au-dessus de 10 pour cent, c'est simplement trop de contenu pour trop peu de performance par cœur. Il faut alors répartir sur plusieurs instances ou augmenter la puissance de calcul, pas tourner le prochain bouton de configuration.
Seuls les joueurs ont des pings élevés, le serveur est calme. Le problème vient alors du réseau. Un emplacement offrant des trajets courts jusqu'à vos joueurs fait ici la plus grande différence. Pour des serveurs à Francfort-sur-le-Main, les latences typiques depuis l'Europe de l'Ouest se situent dans le bas de la plage à deux chiffres. Si les coupures surviennent soudainement et de façon groupée, une attaque peut aussi se cacher derrière, voir Protéger un serveur contre les attaques DDoS. Côté client, des messages de ce genre apparaissent alors :
Internal Exception: io.netty.handler.timeout.ReadTimeoutException
Timed out
Connection reset
À quoi reconnaissez-vous que le problème est réellement réglé
Un correctif n'est confirmé que lorsqu'il tient sous exactement la charge qui a fait apparaître le problème. La nuit, avec deux joueurs, même un serveur cassé tourne rond. Vérifiez aux heures de pointe :
spark tpsaffiche 20,0 sur la fenêtre de 15 minutes, et pas seulement sur celle de 5 secondes.- Le 95e percentile du temps de tick est sous 40 ms, le maximum sous 100 ms.
- 24 heures de log sans une seule ligne « Can't keep up! ».
- Un nouveau profil Spark ne montre plus aucun poste isolé au-dessus de 15 pour cent.
spark gcmonitorne signale aucune pause au-dessus de 200 ms.- Les joueurs qui s'étaient manifestés confirment l'amélioration au même endroit et dans la même situation de jeu.
Notez vos valeurs avant et après, idéalement avec la date et la modification effectuée à chaque fois. Lors du prochain décrochage, dans trois mois, cette liste vaudra plus que n'importe quel guide, car elle montre ce qui a déjà fonctionné sur votre serveur à vous. Si vous réinstallez le serveur, vous trouverez les bases adaptées dans Installer un serveur Minecraft sur Debian et dans la liste de contrôle pour un nouveau serveur root.
Questions fréquentes
Comment savoir si c'est le serveur ou ma connexion internet qui lag ?
Que signifie le message Can't keep up! Is the server overloaded ?
Faut-il encore installer Spark comme plugin ?
Quelles valeurs choisir pour view-distance et simulation-distance ?
Est-ce que plus de RAM aide contre des TPS basses ?
Pourquoi un processeur avec beaucoup de cœurs apporte-t-il peu à Minecraft ?
La prégénération des chunks aide-t-elle vraiment contre les saccades ?
2026 KernelHost GmbH. Tous droits réservés. Ce guide est protégé par le droit d'auteur. Sa republication sur d'autres sites web, même partielle ou sous une forme modifiée, n'est pas autorisée sans notre accord écrit. Les citations accompagnées de la source et d'un lien sont expressément les bienvenues.

