Benchmarks

À quel point FerrFlow est-il rapide ?

Comparaison côte à côte face aux outils de release de l'écosystème JavaScript, mesurée avec hyperfine sur le même matériel, les mêmes commits et les mêmes fixtures. Les chiffres sont rafraîchis à chaque release de FerrFlow.

Dernière mise à jour : September 7, 2026, ferrflow v7.21.1, taille du binaire 8.0 MB

ferrflow changesets commit-and-tag-version semantic-release standard-version

Médiane de 30 runs hyperfine · échelle linéaire · cache froid · FerrFlow épinglé à --jobs 1 · plus bas est meilleur. Le segment pâle au pied de chaque barre est le démarrage de l'outil — lancement du processus, boot du runtime, chargement des modules — mesuré contre une fixture plancher d'un package et un commit ; le segment coloré au-dessus est le travail. Le total est ce que vous attendez ; le découpage dit où il part.

Latence médiane, release --dry-run
Tool1 × 10010 × 10050 × 500100 × 1k50 × 5k200 × 10k50 × 300, graph
ferrflow7 ms10 ms25 ms54 ms193 ms583 ms22 ms
changesets536 ms568 ms626 ms694 ms678 ms636 ms638 ms
commit-and-tag-version481 ms489 ms528 ms600 ms941 ms1.07 s517 ms
semantic-release1.44 s1.35 s1.48 s1.58 s2.35 s2.45 s1.54 s
standard-version550 ms534 ms606 ms652 ms1.13 s1.34 s600 ms

Comment on mesure

  • Hyperfine avec 3 runs de warmup et 30 runs chronométrés par cellule (fixture × outil × commande). Latence médiane rapportée.
  • Cache froid. FerrFlow mémoïse son analyse dans .git/ferrflow-cache. Ce cache est vidé avant chaque run chronométré, pour que la comparaison mesure le travail lui-même — aucun des autres outils n'a d'équivalent derrière lequel s'abriter. Les chiffres à chaud sont rapportés séparément plus bas.
  • Peak RSS via /usr/bin/time -v sur un run supplémentaire unique.
  • Les fixtures sont générées depuis FerrLabs/Fixtures avec un historique de commits conventionnels déterministe (aucune entrée instable). Le nombre de commits dans chaque label de fixture correspond au nombre de commits depuis le dernier tag de release — la fenêtre exacte que FerrFlow parcourt pour calculer un bump, pas l'historique total du dépôt.
  • Toutes les commandes sont des dry runs de planification de release — chaque outil calcule la prochaine version et les notes de release sans rien écrire : ferrflow release --dry-run, semantic-release --dry-run --no-ci, standard-version --dry-run, commit-and-tag-version --dry-run, etc. La même opération pour tous les outils, donc on compare le coût de planification, pas le coût IO de la modification réelle des fichiers.
  • Comparaison mono-thread. FerrFlow tourne avec --jobs 1 dans le graphe ci-dessus, il est donc mesuré comme les outils JS mono-thread. Ses chiffres parallèles réels sont rapportés séparément.
  • Une ligne n'est pas à armes égales, et on préfère le dire que gagner en silence. changesets planifie ses releases à partir de fichiers .changeset/*.md écrits à la main, jamais à partir des commits. Six de nos sept fixtures ne lui en donnent aucun : il annonce aucun package à bumper et s'arrête. Son temps suit le nombre de packages, pas l'historique : il bouge à peine sur une plage de commits 100×, parce qu'il ne les lit pas. Là où nous passons devant, l'essentiel de l'écart tient au démarrage de npx et de Node, pas à la planification de release. Retirez ce démarrage, comme le fait la décomposition du graphique ci-dessus, et sur la plus grande fixture changesets passe moins de temps à travailler que nous, parce qu'il en fait moins. Lisez cette ligne comme une différence de métier, pas comme un verdict. La fixture 50 × 300, graph est le cas inverse : nous y résolvons une cascade de dépendances sur 50 packages et rattrapons les releases manquées dans l'historique, là où les autres émettent un bump et n'ont aucune notion de graphe de dépendances.
  • Reproductible — le pipeline complet est dans FerrLabs/Benchmarks ; les résultats sont publiés en artifacts à chaque push sur main et dans chaque note de release.

Mode parallèle

La comparaison épingle FerrFlow à un seul thread (--jobs 1) pour rester à armes égales avec les outils JS mono-thread. En CI réelle, il est libre d'utiliser tous les cœurs, donc ce tableau mesure ce que ça apporte réellement. Voici le même release --dry-run sur les 4 cœurs du runner de benchmark.

Fixture1 thread4 cœursAccélération
Single package, 100 commits7 ms8 ms0.9×
Monorepo, 10 packages × 100 commits10 ms10 ms1.0×
Monorepo, 50 packages × 500 commits25 ms24 ms1.0×
Monorepo, 100 packages × 1k commits54 ms57 ms0.9×
Monorepo, 50 packages × 5k commits193 ms192 ms1.0×
Monorepo, 200 packages × 10k commits583 ms588 ms1.0×
Monorepo, dependency graph, 50 packages × 300 commits22 ms25 ms0.9×

Cache chaud

Tous les chiffres ci-dessus sont mesurés à froid. En pratique, un dépôt bouge rarement entre deux appels à ferrflow check : FerrFlow conserve donc le résultat de sa dernière analyse dans .git/ferrflow-cache et le réutilise tant que HEAD, les tags et la config n'ont pas changé. Voici ce que coûte un second appel sur un dépôt inchangé — c'est une vraie propriété de l'outil, mais ce n'est pas une comparaison à armes égales, donc ça reste hors du graphe.

FixtureÀ froidEn cacheAccélération
Single package, 100 commits8 ms3 ms2.3×
Monorepo, 10 packages × 100 commits11 ms4 ms2.9×
Monorepo, 50 packages × 500 commits25 ms4 ms5.7×
Monorepo, 100 packages × 1k commits53 ms6 ms8.3×
Monorepo, 50 packages × 5k commits190 ms5 ms41.3×
Monorepo, 200 packages × 10k commits579 ms5 ms125.9×
Monorepo, dependency graph, 50 packages × 300 commits23 ms4 ms5.3×

Empreinte d'installation

Taille sur disque après installation. release-please n'apparaît qu'ici — son runtime ne peut pas être benché hors ligne (il a besoin de l'API GitHub pour résoudre la dernière release), donc l'empreinte est la comparaison équitable qu'on peut publier.

Outilnpm installBinaire natif
ferrflow8.0 MB8.0 MB
changesets5.0 MB
commit-and-tag-version8.0 MB
release-please95.0 MB
semantic-release69.0 MB
standard-version21.0 MB

Pourquoi FerrFlow affiche de plus petits chiffres

  • Binaire natif. Pas de boot Node.js, pas de npm install, pas de découverte de plugins. Un ferrflow check sur un monorepo de 50 packages se termine avant même que node --version ait eu le temps de chauffer.
  • gitoxide in-process. L'énumération des tags et le parcours des commits passent par gitoxide dans le même processus. Les concurrents délèguent à git à chaque appel ; le coût de spawn de processus domine sur les historiques denses.
  • Un seul outil, pas un arbre de plugins. semantic-release tire une chaîne d'analyzers, de générateurs de notes, de publishers npm et d'écrivains de changelog, chacun avec son propre coût de require(). Le pipeline de FerrFlow est une seule crate Rust.

Chiffres mis à jour à chaque release. Voir les dernières notes de release pour le tableau complet, delta baseline inclus.