Profilage (expérimental)

/bench profile montre quel code occupe les threads de tick de votre serveur : quels plugins, quelles parties du serveur, quelles méthodes. Il les échantillonne avec Java Flight Recorder (JFR), le profileur intégré aux versions de Java que VoxelBench prend en charge : rien à télécharger.

Expérimental. Le profileur fonctionne et s'utilise sans risque, mais sa sortie et ses réglages peuvent encore changer d'une version à l'autre. Les profils sont écrits dans plugins/VoxelBench/reports/profiles/ sur votre serveur. Rien n'est envoyé à voxelbench.com sauf si vous envoyez un profil à votre compte ou le partagez par lien public vous-même, un à la fois, par une commande qui le nomme (ajoutez preview pour voir ce qu'il contient avant que rien ne parte).

Il répond à la question « qui tourne sur le thread de tick ? », en pourcentages. Il ne remplace pas un benchmark : le benchmark mesure la vitesse de votre serveur, le profileur dit où passe son temps.

Démarrage rapide

/bench profile            → un joueur reçoit un formulaire (durée, intervalle, garder/partager/envoyer) ; la console capture 30 s
/bench profile 30         → profile les threads de tick pendant 30 s, puis affiche un résumé
/bench profile 60         → la même chose sur 60 s
/bench profile list       → profils enregistrés
/bench profile show 1     → réaffiche le profil enregistré le plus récent

Lancez la capture avant la charge que vous voulez observer. Depuis la console, une commande tapée pendant que le thread de tick est bloqué ne s'exécute qu'une fois celui-ci libéré.

Commandes

Toutes les commandes du profileur exigent voxelbench.profile (opérateurs uniquement par défaut), en plus de voxelbench.use ; upload exige aussi voxelbench.profile.upload, et share / unshare exigent voxelbench.profile.share. Elles fonctionnent toutes depuis la console.

CommandeDescription
/bench profile [secondes] [période-ms] [upload|share]Capture minutée : 30 s par défaut (5 à 300), un échantillon demandé toutes les 10 ms par défaut (10 à 50). Une valeur hors bornes est refusée, pas modifiée en silence. Avec upload (alias send) ou share, le nouveau profil part dès qu'il est enregistré
/bench profile ring onDémarrer le tampon circulaire continu (voir plus bas)
/bench profile ring offL'arrêter ; son contenu est abandonné
/bench profile ring dump [secondes] [upload|share]Analyser les N dernières secondes du tampon (60 par défaut, au plus max-age-seconds) sans l'arrêter ; avec upload ou share, envoyer le résultat une fois enregistré
/bench profile ring statusÉtat du tampon circulaire et des vidages automatiques
/bench profile listProfils enregistrés, du plus récent au plus ancien, numérotés (#1 = le plus récent)
/bench profile show <numéro|id|last>Réafficher le résumé d'un profil enregistré. Un préfixe unique de l'identifiant suffit
/bench profile delete <numéro|id|last>Supprimer un profil enregistré (et son .jfr brut s'il est conservé)
/bench profile upload <numéro|id|last> [preview]Envoyer tout de suite le profil à votre compte voxelbench.com (alias send) ; preview montre seulement ce qui partirait (voir plus bas)
/bench profile share <numéro|id|last> [preview]Publier tout de suite une copie nettoyée derrière un lien public (sans compte, 7 jours) ; preview montre seulement ce qui partirait (voir plus bas)
/bench profile unshare <numéro|id|last>Supprimer le lien public d'un profil partagé avant son expiration (possible même après la suppression locale du profil)
/bench profile statusDisponibilité de JFR, capture en cours, tampon circulaire, vidages automatiques, profils enregistrés

Une seule capture minutée tourne à la fois, et les profils sont analysés l'un après l'autre.

Capturer et envoyer en une commande. /bench profile 30 share capture pendant 30 secondes, affiche le résumé, puis partage le nouveau profil par lien public ; /bench profile 30 upload l'envoie plutôt à votre compte, et /bench profile ring dump 60 share fait de même avec le tampon circulaire. Ce qui empêcherait l'envoi — permission manquante, fonction désactivée, serveur non lié, benchmark en cours — est signalé avant le début de la capture. Un vidage automatique sur lag n'est jamais envoyé.

Lire le résumé

Profil 20260924-153012-manual - 30 s, un échantillon demandé toutes les 10 ms (expérimental)
Échantillons : 1045 sur le thread de tick (Server thread), 2016 sur tous les threads. Ce sont des comptes, pas des durées.
self = code au sommet de la pile (les appels au JDK comptent pour leur appelant) ; incl. = n'importe où dans la pile.
Qui tourne sur le thread de tick (self / incl.) :
  server : 83.5 % self, 100.0 % incl. (873 échantillons)
  VoxelBench : 16.4 % self, 17.0 % incl. (171 échantillons)
  spark : 0.1 % self, 0.3 % incl. (1 échantillons)
Méthodes les plus coûteuses (self) :
  Level.tickChunk [server] 22.1 % (231 échantillons)
  ...
Enregistré dans plugins/VoxelBench/reports/profiles/20260924-153012-manual.json (21 Ko).
  • Propriétaires. Chaque méthode échantillonnée est attribuée à un propriétaire :
    • un nom de plugin, pour le code qui vient du jar de ce plugin. Les plugins déclarés par paper-plugin.yml et les bibliothèques qu'un plugin déclare dans libraries: comptent pour ce plugin ;
    • server pour Minecraft, Bukkit, Paper et les bibliothèques livrées avec le serveur ;
    • jvm pour Java lui-même ;
    • library pour un jar libraries: déclaré par plusieurs plugins, ou dont le plugin n'a pas pu être déterminé ;
    • spark pour la copie de spark intégrée à Paper ;
    • other pour tout le reste (code généré, agents).
  • self fait 100 % au total : chaque échantillon va au propriétaire du cadre de plugin le plus profond de la pile, si bien que le code du serveur appelé par un plugin compte pour ce plugin. Sans plugin dans la pile, c'est le cadre hors JDK le plus profond qui décide. Un écouteur du plugin B, appelé pendant une action du plugin A, compte pour B.
  • incl. (inclusif) compte un échantillon pour chaque propriétaire présent n'importe où dans la pile. Le plugin A ci-dessus y retrouve le temps de B qu'il a déclenché.
  • Les méthodes les plus coûteuses sont celles au sommet de la pile, les appels au JDK étant repliés dans leur appelant (HashMap.get n'apprend rien ; la méthode du serveur ou du plugin qui l'appelle, si).
  • Des comptes, pas des durées. JFR livre moins d'échantillons que la période ne le promet (sous Windows l'horloge est grossière, et JFR n'échantillonne que quelques threads par tour) : « échantillons × période » n'est pas une durée. Lisez les pourcentages ; servez-vous des comptes pour juger de leur fiabilité.
  • Qui tourne n'est pas qui a causé. Un profil montre le code qui s'exécute. Un plugin qui pose mille entonnoirs n'apparaît pas quand le serveur les fait tourner : ce temps-là est du server.
  • Les plugins obfusqués sont correctement attribués, mais leurs noms de méthodes ne veulent rien dire.

Avertissements de qualité

Le résumé (et le fichier JSON) peuvent ajouter :

AvertissementSignification
Seulement N échantillons de tickMoins de 300 échantillons sur les threads de tick : les pourcentages ne sont qu'indicatifs. Capturez plus longtemps, ou pendant que le serveur travaille
N % des piles dépassaient la limite de JFRJFR garde 64 cadres par défaut ; les piles plus profondes perdent leur racine. Démarrez le serveur avec -XX:FlightRecorderOptions:stackdepth=256 si cela revient souvent
N threads travaillaient en même tempsJFR n'échantillonne qu'environ cinq threads Java par tour : le thread de tick a reçu moins d'échantillons. Les parts restent justes, mais plus bruitées
Un autre enregistrement JFR échantillonne toutes les N msUn autre outil (ou un jcmd JFR.start manuel) a demandé une période plus courte, que JFR applique à tous les enregistrements. Les comptes sont plus élevés que prévu ; les pourcentages ne changent pas. Seuls les enregistrements encore actifs au moment du vidage sont détectés : un vidage du tampon qui couvre une capture plus rapide déjà terminée ne porte pas cet avertissement
N échantillons ont eu leur pile coupéeLes tables du profil étaient pleines (vidage très volumineux). Les échantillons comptent toujours, imputés à un appelant
Le tampon ne couvrait que N sLe tampon circulaire ne tournait pas depuis toute la fenêtre demandée

Tampon circulaire

Le tampon circulaire est un enregistrement JFR continu qui ne garde que les dernières minutes d'échantillons, pour analyser un lag après coup. Il est désactivé par défaut :

  • profiling.ring.enabled-on-start: true le démarre avec le serveur ;
  • /bench profile ring on / off le bascule en cours de route (jusqu'au prochain redémarrage).

Il échantillonne toutes les 20 ms par défaut et garde les 300 dernières secondes, au plus 32 Mo, dans le dépôt de JFR situé dans le répertoire temporaire de la JVM (JFR l'efface à un arrêt propre). /bench profile ring dump en analyse une partie sans l'arrêter.

Vidage automatique sur lag

Tant que le tampon circulaire tourne, VoxelBench peut le vider et l'analyser de lui-même quand le serveur lague (profiling.auto-dump.enabled, activé par défaut ; sans effet tant que le tampon est arrêté).

Comment un lag est détecté. Une minuterie tourne à chaque tick et mesure le temps écoulé entre deux ticks (sous Spigot et Paper, c'est la durée du tick précédent). Un lag, c'est :

  • consecutive-slow-ticks ticks d'affilée (40 par défaut) qui durent chacun au moins slow-tick-ms (100 ms par défaut, soit moins de 10 TPS pendant au moins 4 secondes), ou
  • un seul tick d'au moins freeze-ms (1000 ms par défaut). Un gel ne se voit qu'une fois terminé, quand le tick suivant tourne enfin ; le tampon a de toute façon gardé ses échantillons.

Ce qui est vidé. Le profil couvre de 10 s avant le début du lag à 5 s après sa détection (VoxelBench attend ces 5 s avant de vider). Il est enregistré avec le déclencheur lag, et son résumé dit ce qui l'a déclenché. Le journal du serveur reçoit une ligne avec le nom du fichier et les principaux propriétaires ; rien n'est envoyé aux joueurs.

Ce qui empêche un vidage :

  • cooldown-seconds (300 par défaut) : au plus un vidage automatique par période, pour qu'un serveur en difficulté n'écrive pas un profil toutes les quelques secondes ;
  • les 30 premières secondes après le (re)démarrage du tampon, dont les ticks sont toujours lents ;
  • un test VoxelBench en cours, dont la charge est voulue, et les 30 secondes qui suivent sa fin (son nettoyage tourne une fois le verrou du test libéré et peut tenir un tick plusieurs secondes) ;
  • un autre profil en cours d'analyse à ce moment-là.

Serveurs vides. Minecraft 1.21.2 et suivants peuvent suspendre un serveur sans joueur connecté (pause-when-empty-seconds dans server.properties : 60 par défaut chez Spigot, désactivé chez Paper). Le tick qui reprend après une telle pause ressemblerait à un gel : quand ce réglage est actif, un long tick survenant juste après une période sans joueur est donc ignoré. Les séries de ticks lents restent détectées.

Sous Folia, la minuterie tourne sur la région globale. Un lag cantonné à une région, sur un serveur à plusieurs threads de région, ne ralentit pas la région globale et n'est pas détecté ; utilisez alors /bench profile ring dump. Avec un seul thread de région, la région globale le partage et les lags sont détectés.

Aucun run noté n'est profilé

Un benchmark qui produit un score ne doit dépendre de rien d'autre qui tourne. Pendant un run noté — /bench start (y compris multi-run et profils personnalisés), /bench stresslimit, /bench tier, un job lancé par l'agent d'auto-bench, ou un /bench test dont le résultat part sur voxelbench.com — le profileur :

  • refuse de démarrer une capture ou un vidage du tampon, en le disant ;
  • annule une capture minutée en cours (rien n'est enregistré) ;
  • interrompt une analyse en cours ;
  • arrête le tampon circulaire (son contenu est abandonné) et la détection de lag.

Il reprend 30 s après la fin du run noté, ce qui couvre aussi la pause entre les itérations d'un multi-run. Le tampon circulaire redémarre alors vide.

Un test lancé par /bench test n'est un run noté que si son résultat quitte la machine : quand l'envoi des tests unitaires sur voxelbench.com est actif (reports.backend.unit-tests et serveur lié), ou quand l'agent d'auto-bench l'a lancé. Sinon il reste local et peut être profilé — un bon moyen de voir à quoi un test passe son temps. Pour profiler un test sur un serveur qui envoie ses résultats, désactivez reports.backend.unit-tests le temps de la session.

Profils enregistrés

Chaque profil est un fichier JSON dans plugins/VoxelBench/reports/profiles/, nommé <date>-<heure>-<déclencheur>.json (heure locale du serveur), par exemple 20260924-153012-lag.json. Le déclencheur est manual (capture minutée), ring (ring dump) ou lag (vidage automatique).

  • Rétention. Après chaque nouveau profil, les plus anciens sont supprimés tant qu'il y en a plus de storage.max-files (20) ou qu'ils occupent plus de storage.max-total-mb (100 Mo). Le profil qui vient d'être écrit n'est jamais supprimé par sa propre rétention.
  • Vidage brut. Avec storage.keep-raw-jfr: true, le fichier .jfr brut est gardé à côté du JSON ; ouvrez-le avec JDK Mission Control. Un vidage du tampon contient tout le tampon, tous les threads compris. Désactivé par défaut.
  • Format. Le champ schema (voxelbench-profile/1) identifie le format. Le fichier contient les réglages de la capture, la plateforme et la version de Java, les comptes d'échantillons par genre de thread (tick, ordonnanceur, serveur, jvm, autre), l'attribution par propriétaire, les méthodes les plus coûteuses, les avertissements, un arbre d'appels élagué (les nœuds sous 0,5 % des échantillons sont fondus dans leur parent, 1 500 nœuds au plus) et des diagnostics. Il peut changer tant que la fonction est expérimentale.
  • Dossier. Les profils vivent dans le dossier profiles/ du dossier des rapports (reports.folder, reports par défaut), à côté de vos rapports. Les profils enregistrés par une version antérieure dans plugins/VoxelBench/profiles/ y sont déplacés au démarrage du serveur, traces d'envoi et de partage comprises ; rien n'est écrasé (si un nom est déjà pris, le profil déplacé reçoit le suffixe -2 et le journal du serveur le dit), et l'ancien dossier est supprimé une fois vide.
  • Nettoyage des rapports. /bench reports cleanup et le bouton Nettoyer du menu Rapports ne suppriment que d'anciens rapports. Ils ne touchent jamais aux profils, qui gardent leur propre rétention ci-dessus.

Dans le menu et le tableau de bord web

/bench gui → Profileur (menu principal) pilote le profileur sans rien taper :

  • Capturer 30 s / 60 s / 120 s, et Vider le tampon (60 s) ;
  • Après l'enregistrement : garder le profil sur le serveur (par défaut), le partager par lien public, ou l'envoyer sur voxelbench.com. Ces deux derniers choix n'apparaissent qu'avec leur permission, et demandent une confirmation avant le début de la capture ;
  • Tampon circulaire marche/arrêt, et État complet dans le chat (/bench profile status) ;
  • l'état du moment : capture en cours, tampon circulaire, pause autour d'un run noté, profils enregistrés.

/bench gui → Rapports → Profils liste les profils enregistrés, du plus récent au plus ancien : date, déclencheur, fenêtre, échantillons de tick, plugin le plus lourd, et les badges Envoyé sur voxelbench.com / Partagé jusqu'au …. Un clic ouvre sa fiche : en-tête (identifiant, date, fenêtre, versions du serveur et de Java), qui tourne sur le thread de tick (self / incl.), méthodes les plus coûteuses, avertissements, état de l'envoi et du lien public (clic : les liens dans le chat), et les boutons Afficher dans le chat, Aperçu (clic : ce qu'un lien public publierait ; Maj-clic : ce qu'un envoi transmettrait), Partager par lien public, Envoyer sur voxelbench.com, Supprimer le lien public et Supprimer. Partager, envoyer et supprimer demandent d'abord une confirmation.

Chaque bouton lance pour vous la commande /bench profile correspondante : les permissions, les refus et les messages sont exactement ceux de la commande. Les écrans exigent voxelbench.profile, et Partager / Envoyer sont grisés sans voxelbench.profile.share / voxelbench.profile.upload.

Tableau de bord web. Quand le tableau de bord de monitoring est activé, sa page a une section Profils en lecture seule : la même liste, et le résumé d'un profil (plugins, méthodes, avertissements, envoi et partage, avec les liens). Elle est servie par GET /api/profiles et GET /api/profiles/<id>, avec la même connexion ou clé d'API que /api/metrics et les deux listes blanches d'IP (modes dashboard et api). Rien ne se capture, ne se partage, ne s'envoie ni ne se supprime depuis le web, et le tableau de bord ne montre jamais le jeton qui supprime un lien public. La section n'existe pas en mode API seule (monitor.dashboard.enabled: false).

Envoyer un profil sur voxelbench.com

Un profil enregistré peut être envoyé au compte voxelbench.com auquel votre serveur est lié, pour le lire là-bas ou le montrer à qui vous aide. C'est toujours manuel : VoxelBench n'envoie jamais un profil de lui-même (pas même un vidage automatique sur lag), et jamais autre chose que le profil que vous désignez.

  1. Liez d'abord le serveur : /bench link (voir Liaison de compte).
  2. /bench profile upload <numéro|id|last> l'envoie tout de suite — /bench profile upload last envoie le profil le plus récent, et /bench profile 30 upload en capture un et l'envoie une fois enregistré. Si un nom de thread ou de méthode semble contenir une adresse ou un chemin, le chat le dit d'abord : un envoi transmet le fichier tel quel, à votre seul compte.
  3. Pour regarder avant d'envoyer, ajoutez preview : /bench profile upload <numéro|id|last> preview montre ce qui quitterait le serveur, et n'envoie rien :
    Envoyer le profil 20260924-153012-manual sur voxelbench.com ? (expérimental)
    Il part vers le compte auquel ce serveur est lié sur voxelbench.com, où tu pourras le consulter et le supprimer.
    Ce qui part : le fichier plugins/VoxelBench/reports/profiles/20260924-153012-manual.json tel quel, 21 Ko (6 Ko compressés). Il contient :
      - les noms de 3 plugins : VoxelBench, LuckPerms, spark
      - 212 noms de méthodes (classe et méthode du code échantillonné, plugins privés compris) et 18 noms de threads ;
      - la version du serveur (1.21.11-...), Java 21.0.11 (Eclipse Adoptium), Linux amd64, 8 threads processeur, et les heures de la capture.
    Aucun nom de joueur, UUID, adresse IP, nom de monde, coordonnée ni commande.
    Pour l'envoyer, lance /bench confirm dans les 60 s. Sinon, rien n'est envoyé.
    
    /bench profile upload <id> confirm (ou /bench confirm, un clic sur cette ligne, ou Oui dans la fenêtre qui s'ouvre) envoie alors exactement ce qui a été montré : dans les 60 s, pour le profil que vous venez de consulter, depuis le même joueur ou la même console, et seulement si le fichier n'a pas changé entre-temps. Un confirm sans preview préalable est refusé.

Une fois envoyé, le profil est marqué envoyé dans /bench profile list, et /bench profile show affiche le lien vers sa page sur voxelbench.com.

Ce qui part. Exactement le fichier JSON que vous pouvez ouvrir dans plugins/VoxelBench/reports/profiles/, compressé : jamais le vidage .jfr brut, jamais un autre profil, rien d'ajouté. Son contenu est décrit dans Confidentialité.

Quand c'est refusé :

  • le serveur n'est pas lié, ou profiling.upload.enabled vaut false ;
  • vous n'avez pas voxelbench.profile.upload (les opérateurs l'ont par défaut ; voxelbench.profile ne l'accorde pas) ;
  • un run noté est en cours, ou s'est terminé il y a moins de 30 s : un envoi utilise le réseau que le benchmark mesure ;
  • le fichier dépasse profiling.upload.max-size-kb (1024 Ko par défaut) ;
  • un autre envoi est en cours, ou le précédent date de moins de 30 s (ou voxelbench.com a demandé d'attendre plus longtemps).

Réponses de voxelbench.com. Le chat dit ce qui s'est passé : envoyé (avec un lien), déjà sur le site, liaison plus reconnue (lancez /bench link force), offre sans envoi de profils, trop volumineux, trop d'envois (avec le délai à attendre), erreur du site, pas de réponse. Tant que voxelbench.com n'accepte pas les profils, la réponse est « voxelbench.com ne sait pas encore recevoir de profils » : rien n'est enregistré et il n'y a rien à corriger de votre côté.

Supprimer. /bench profile delete ne supprime que la copie locale, et rappelle que la copie envoyée reste sur voxelbench.com : supprimez-la sur le site.

Partager un profil par lien public

Pour montrer un profil à quelqu'un qui n'a pas accès à votre compte — typiquement, coller un lien dans un salon Discord pour se faire aider — partagez-le par lien public. Ce mode ne demande ni compte ni serveur lié : voxelbench.com répond par un lien non listé, que toute personne qui l'a peut ouvrir, et qui expire au bout de 7 jours. Rien ne le liste ni ne l'indexe : il est aussi privé que le lien lui-même.

  1. /bench profile share <numéro|id|last> le publie tout de suite — /bench profile share last partage le profil le plus récent, et /bench profile 30 share en capture un et le partage une fois enregistré. Le chat dit d'abord ce qui a été retiré de la copie, puis affiche le lien (cliquable) et sa date d'expiration.
  2. Pour regarder avant de publier, ajoutez preview : /bench profile share <numéro|id|last> preview montre ce qui serait publié, et n'envoie rien :
    Partager le profil 20260924-153012-manual par un lien public ? (expérimental)
    Lien PUBLIC : toute personne qui a le lien verra ce profil. Il expire au bout de 7 jours. Aucun compte n'intervient, et rien n'est listé ni indexé.
    Il part vers voxelbench.com, qui répond avec le lien. Le site n'utilise l'identifiant de ce serveur que pour limiter les abus et ne l'affiche jamais.
    Ce qui part : une copie nettoyée de plugins/VoxelBench/reports/profiles/20260924-153012-manual.json, 21 Ko (6 Ko compressés). Elle contient :
      - les noms de 3 plugins : VoxelBench, LuckPerms, spark
      - 212 noms de méthodes (classe et méthode du code échantillonné, plugins privés compris) et 18 noms de threads ;
      - la version du serveur (1.21.11-...), Java 21.0.11 (Eclipse Adoptium), Linux amd64, 8 threads processeur, et les heures de la capture.
    Retiré avant le partage : 2 noms de threads et 0 autres noms contenaient une adresse, un chemin ou un nom, remplacés par [ip], [host].
    Jamais dans un profil partagé : noms de joueurs, UUID, adresses IP, noms de mondes, chemins de fichiers, identifiant de ce serveur, son jeton de liaison ni ton compte.
    Pour le publier, lance /bench confirm dans les 60 s. Sinon, rien n'est envoyé.
    
    /bench profile share <id> confirm (ou /bench confirm, un clic sur cette ligne, ou Oui dans la fenêtre qui s'ouvre) publie alors exactement cette copie, avec les mêmes règles qu'un envoi : dans les 60 s, même joueur ou console, même profil, fichier inchangé.

/bench profile list marque le profil partagé jusqu'au <date>, et /bench profile show affiche le lien tant qu'il est valide.

Ce qui est publié. Une copie nettoyée du fichier JSON, jamais le fichier lui-même ni le .jfr brut :

  • Gardé — ce qui fait l'utilité du profil : noms des plugins, noms de classes et de méthodes, noms des threads, attribution par propriétaire, arbre d'appels, avertissements, versions du serveur et de Java, système, nombre de processeurs, heures de la capture.
  • Retiré des noms de threads, de méthodes et de chargeurs de classes, remplacé par un repère comme [ip] : adresses IP (le thread RCON de Minecraft porte l'IP du client) et leur port, noms d'hôtes (les pilotes de bases de données mettent le leur dans le nom de leurs threads), URL, adresses e-mail, chemins de fichiers, UUID, longues chaînes hexadécimales (jetons, empreintes), et les noms que ce serveur connaît : joueurs connectés, mondes (sauf world, world_nether, world_the_end par défaut), utilisateur système et nom de la machine, dossier du serveur, identifiant du serveur et jeton de liaison. Une classe qu'un moteur de scripts a nommée d'après le chemin d'un script perd ce chemin.
  • Pas recopié du tout : tout champ dont VoxelBench ne sait pas qu'il peut être public. Une version future qui ajoutera un champ aux profils ne le publiera pas avant de l'avoir examiné pour le partage public.

Le chat dit combien de noms ont été nettoyés, et par quels repères. Le nettoyage reconnaît des motifs et les noms ci-dessus ; il ne peut pas deviner le nom d'un joueur hors ligne qu'un plugin aurait mis dans un nom de thread — en cas de doute, vérifiez d'abord la liste des plugins et les comptes avec preview.

Qui peut partager. Seuls les builds officiels de VoxelBench : voxelbench.com vérifie la signature du jar, comme pour les rapports de benchmark. Un build de développement ou modifié reçoit « Ce build de VoxelBench ne peut pas partager de profils » et rien n'est envoyé ; /bench profile upload fonctionne toujours avec un serveur lié. Le site reçoit l'identifiant de ce serveur avec la requête, uniquement pour limiter les abus (un nombre de partages par serveur et par adresse) ; il ne l'affiche jamais et ne relie pas le lien à votre serveur.

Supprimer le lien avant son expiration. /bench profile unshare <numéro|id|last> le supprime aussitôt sur voxelbench.com : le lien ne fonctionne plus. La commande utilise un jeton de suppression que voxelbench.com a rendu à la création du lien, gardé seulement dans plugins/VoxelBench/reports/profiles/<id>.share.json (qui a ce fichier peut supprimer le lien, rien de plus). unshare fonctionne même après /bench profile delete — supprimer un profil en local ne supprime pas son lien public, et le message de suppression le rappelle — et même avec profiling.share.enabled: false. Une fois le lien expiré, la trace locale disparaît d'elle-même.

Quand c'est refusé :

  • profiling.share.enabled vaut false, ou vous n'avez pas voxelbench.profile.share (les opérateurs l'ont par défaut ; ni voxelbench.profile ni voxelbench.profile.upload ne l'accordent) ;
  • un run noté est en cours, ou s'est terminé il y a moins de 30 s ;
  • la copie nettoyée dépasse profiling.share.max-size-kb (1024 Ko par défaut) ;
  • un autre partage est en cours, ou le précédent date de moins de 30 s (ou voxelbench.com a demandé d'attendre plus longtemps) ;
  • le profil a déjà un lien public en vie : faites d'abord unshare pour en créer un nouveau.

Tant que voxelbench.com ne gère pas les liens publics, la réponse est « voxelbench.com ne sait pas encore partager de profils » : rien n'est publié et il n'y a rien à corriger de votre côté.

Prérequis et limites

  • Java Flight Recorder doit être disponible. Il fait partie de tous les environnements HotSpot que VoxelBench prend en charge (Java 16 à 25 : Temurin, Oracle, Zulu, Corretto…). /bench profile status dit pourquoi il ne l'est pas :
    • pas de module jdk.jfr : un environnement minimal construit avec jlink sans JFR ;
    • désactivé ou non pris en charge : la JVM a été lancée avec -XX:-FlightRecorder, ou ce n'est pas HotSpot (OpenJ9 / IBM Semeru n'ont pas JFR). Le reste de VoxelBench n'est pas concerné.
  • Seuls les threads de tick sont analysés : Server thread sous Spigot et Paper, les threads d'ordonnancement des régions sous Folia. Les autres threads sont seulement comptés.
  • Un profil de lag sans aucun échantillon de tick. Le thread de tick n'exécutait pas de Java pendant la fenêtre : il attendait, dormait, ou manquait de CPU faute que l'hôte lui en donne (une machine mutualisée surchargée, par exemple). Le profil le signale tel quel ; la cause est hors de la JVM.
  • Seul le code qui s'exécute est échantillonné. JFR échantillonne un thread pendant qu'il exécute du Java, pas pendant qu'il attend (la génération de chunks sur les threads de travail, le disque, un verrou) ni quand il dort entre deux ticks. Un serveur au repos ne donne presque aucun échantillon, et un gel avec très peu d'échantillons de tick indique un thread de tick qui attendait plutôt qu'il ne calculait.
  • Surcoût. Dans nos mesures, l'échantillonnage JFR à 10 ou 20 ms n'a ajouté aucun temps de tick mesurable. L'analyse d'un vidage prend une fraction de seconde d'un cœur, hors du thread de tick.
  • Cohabitation. Le profileur tourne à côté de spark (y compris la copie intégrée à Paper) et d'autres enregistrements JFR. Plusieurs enregistrements JFR partagent la période la plus courte demandée.
  • Profondeur de pile. JFR garde 64 cadres par pile, sauf si le serveur est lancé avec -XX:FlightRecorderOptions:stackdepth=N.
  • Mémoire. La lecture se fait en flux et reste bornée (cadres distincts, nœuds de l'arbre et profondeur de pile sont plafonnés), même pour un gros vidage du tampon.

Confidentialité

Un profil contient les noms de classes et de méthodes du code échantillonné, qui révèlent vos plugins installés (y compris privés), les noms des plugins et des threads, vos versions de serveur et de Java, le système d'exploitation, le nombre de processeurs et des horodatages. Ses champs ne contiennent aucun nom de joueur, UUID, nom de monde, coordonnée, commande, chemin de fichier ni argument de la JVM. Les noms des threads sont écrits tels que Java les donne, et peuvent parfois contenir une adresse ou un nom : le thread RCON de Minecraft s'appelle RCON Client /<IP du client>, et les pilotes de bases de données mettent le nom d'hôte de leur serveur dans les leurs.

Les profils restent sur votre serveur. Seules deux commandes en envoient un, quand un opérateur les tape — directement, ou après un preview —, un profil à la fois, jamais automatiquement :

  • /bench profile upload <id> : le fichier JSON tel quel part vers le compte voxelbench.com auquel le serveur est lié, privé pour ce compte. Si un nom de thread semble contenir une adresse ou un chemin, le chat le dit.
  • /bench profile share <id> : une copie nettoyée (adresses, noms d'hôtes, chemins, noms de joueurs, de mondes et d'utilisateur retirés ; voir plus haut) est publiée derrière un lien public non listé qui expire au bout de 7 jours. Aucun compte n'intervient.

Aucun rapport de benchmark ni envoi du monitoring ne transporte de données de profil. profiling.upload.enabled: false et profiling.share.enabled: false désactivent complètement chacun des deux. Supprimer un profil en local ne supprime ni la copie envoyée (supprimez-la sur voxelbench.com) ni son lien public (/bench profile unshare <id>, ou attendez son expiration).

Configuration

profiling:
  enabled: true
  ring:
    enabled-on-start: false
    period-ms: 20
    max-age-seconds: 300
    max-size-mb: 32
  auto-dump:
    enabled: true
    slow-tick-ms: 100
    consecutive-slow-ticks: 40
    freeze-ms: 1000
    cooldown-seconds: 300
  storage:
    max-files: 20
    max-total-mb: 100
    keep-raw-jfr: false
  upload:
    enabled: true
    max-size-kb: 1024
  share:
    enabled: true
    max-size-kb: 1024

Voir Configuration - Profilage pour chaque clé et ses bornes.