Skip to content

--time-source jfr : mesurer le temps sous Windows, et dire ce que ça coûte - #55

Merged
Beennnn merged 1 commit into
mainfrom
claude/reprise-sans-binaires-fu4e2h
Sep 7, 2026
Merged

--time-source jfr : mesurer le temps sous Windows, et dire ce que ça coûte#55
Beennnn merged 1 commit into
mainfrom
claude/reprise-sans-binaires-fu4e2h

Conversation

@Beennnn

@Beennnn Beennnn commented Sep 7, 2026

Copy link
Copy Markdown
Owner

Windows n'a pas d'arbre d'appels parce qu'async-profiler ne publie pas de binaire pour lui. Flight Recorder est dans le JDK, tourne partout, et le convertisseur que l'outil embarque déjà pour les flammes replie son enregistrement en exactement les piles que CallTree lit déjà. En aval, rien ne distingue les deux — c'est le fond du mécanisme, et c'est aussi son danger.

Ce que ça coûte, et pourquoi c'est explicite

C'est le seul réglage de l'outil dont le prix se paie en justesse. JACOCO_REPORTS et ARCHIVE renoncent à des fichiers ; celui-ci renonce à de la vérité.

async-profiler Flight Recorder
Où l'échantillon est pris depuis un gestionnaire de signal, n'importe où à un point de sûreté
Conséquence la méthode réellement en cours peut nommer son appelant
Cadence 1 ms (--interval) ~10 ms, --interval inopérant
--filter donné à la JVM, qui n'enregistre rien d'autre aucun effet

Le JIT retire les points de sûreté des boucles comptées chaudes : l'échantillonneur ne peut donc pas observer là où le temps passe, il observe le point de sûreté le plus proche. C'est la raison d'exister d'async-profiler, et c'est mesuré, pas théorique.

Un profil moins juste qui ne le dit pas est pire que pas de profil. L'option est donc explicite, jamais un repli automatique, et son prix est écrit aux quatre endroits où elle se propose : l'aide (section MEASURING TIME WITHOUT ASYNC-PROFILER), le gabarit de configuration, la console au lancement, et le rapport lui-même — mise en garde à côté de celle sur les pourcentages, et ligne « Temps mesuré par » dans le contexte de chaque exécution.

Le message d'arbre vide sous Windows gagne cette seconde issue, après WSL qui reste la première : elle ne coûte rien, elle.

Trois défauts trouvés en l'exécutant, pas en la lisant

  • --cpu convertit un enregistrement plein en fichier vide. Ce drapeau cherche jdk.CPUTimeSample, un événement du JDK 25 ; sur plus ancien il écrit zéro ligne à partir de 218 échantillons. La conversion ne demande donc aucun filtre d'événement.
  • Le convertisseur marque les images _[j], _[i], _[0]. Une première passe ne retirait que _[a-z] et laissait RoutePlanner.<clinit>_[0] dans l'arbre — un nom qu'aucun lecteur ne reconnaît.
  • Le premier message de console affirmait que --filter était « appliqué à la lecture ». Il ne l'est pas du tout. Écrire la phrase vraie a coûté trois corrections, aux trois endroits où la fausse avait été recopiée.

Et un quatrième au rendu : la mise en garde portait <code>--time-source jfr</code> en ligne, ce qui découpe le paragraphe en nœuds de texte dont aucun n'est une clé du dictionnaire — la vue française affichait un paragraphe anglais. Une phrase traduite est un nœud de texte, sans balisage.

Capture possède l'emplacement du profil

Chaque outil écrit sous son propre nom — async-profiler/, jfr/ — parce que nommer un répertoire d'après un outil qui n'a pas produit le fichier serait un mensonge discret. Capture.profile() et Capture.profileDir() sont la réponse unique à « où est le profil de cette exécution », pour cinq lecteurs : l'arbre, les deux exports, les flammes brutes et les liens de la page. Une capture ancienne, qui ne connaît qu'async-profiler/, se résout toujours — d'où capture 1.2 et non 2.0.

Vérification

  • 298 tests, dont deux nouveaux : FileCostTest tient la section d'aide (l'issue qui ne coûte rien avant celle qui coûte, le mot SAFEPOINT, les deux cadences, --filter HAS NO EFFECT), ViewContractTest tient les trois endroits où la page le dit, la raison et pas seulement l'étiquette, l'absence de balisage dans la phrase traduite, et sa traduction.
  • 72 vérifications de la recette locale.
  • 0 différence sur les 8 610 chaînes des dix-huit états des deux rapports de référence.
  • Une campagne JFR réelle de bout en bout : 17 462 échantillons, 406 piles repliées, aucun suffixe résiduel, les trois liens pointant sur jfr/.

🤖 Generated with Claude Code

https://claude.ai/code/session_01J956wjynbd7fkZx4HpjHzP


Generated by Claude Code

Windows n'a pas d'arbre d'appels parce qu'async-profiler ne publie pas de binaire
pour lui. Flight Recorder est dans le JDK, tourne partout, et le convertisseur que
l'outil embarque déjà pour les flammes replie son enregistrement en exactement les
piles que CallTree lit déjà : en aval, rien ne distingue les deux. C'est le fond du
mécanisme, et c'est aussi son danger.

Car ce profil est moins vrai. JFR lit une pile à un point de sûreté, et le JIT
retire les points de sûreté des boucles chaudes : l'échantillon tombe sur le point
de sûreté le plus proche, qui peut être l'APPELANT de la méthode réellement en
cours. Il échantillonne dix fois moins souvent, et --filter n'a aucun effet. Un
profil moins juste qui ne le dit pas est pire que pas de profil : l'option est donc
explicite, jamais un repli automatique, et son prix est écrit aux quatre endroits
où elle se propose — l'aide, le gabarit de configuration, la console au lancement,
et le rapport lui-même, sur chaque exécution mesurée ainsi.

Trois défauts trouvés en l'exécutant, pas en la lisant :

--cpu convertit un enregistrement plein en fichier vide — ce drapeau cherche
jdk.CPUTimeSample, un événement du JDK 25, et écrit zéro ligne à partir de 218
échantillons sur plus ancien. Le convertisseur marque les images _[j], _[i] et
_[0] : une première passe ne retirait que _[a-z] et laissait
RoutePlanner.<clinit>_[0] dans l'arbre. Et le premier message de console affirmait
que --filter était « appliqué à la lecture » — il ne l'est pas du tout ; écrire la
phrase vraie a coûté trois corrections, aux trois endroits où la fausse avait été
recopiée.

Capture possède désormais l'emplacement du profil : chaque outil écrit sous son
propre nom, et cinq lecteurs passent par une seule réponse. Une capture ancienne,
qui ne connaît qu'async-profiler/, se résout toujours — d'où 1.2 et non 2.0.

Vérifié : 298 tests, 72 vérifications de recette, 0 différence sur les 8 610
chaînes des dix-huit états, et une campagne JFR réelle de bout en bout.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01J956wjynbd7fkZx4HpjHzP
@Beennnn
Beennnn marked this pull request as ready for review September 7, 2026 11:01
@Beennnn
Beennnn merged commit 534b1b1 into main Sep 7, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants