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 : July 23, 2026 · ferrflow v5.47.0 · 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 ms9 ms10 ms16 ms31 ms64 ms20 ms
changesets762 ms842 ms691 ms880 ms684 ms770 ms769 ms
commit-and-tag-version490 ms500 ms405 ms589 ms716 ms1.08 s487 ms
semantic-release1.58 s1.61 s1.27 s1.79 s1.91 s2.48 s1.45 s
standard-version560 ms567 ms468 ms713 ms881 ms1.32 s561 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.
  • Two cells are not like-for-like, and we'd rather say so than quietly win. On 200 × 10k, changesets status is faster than FerrFlow — but changesets plans releases from .changeset/*.md files you write by hand, and never from commits. Six of our seven fixtures give it none, so it reports no packages to be bumped and stops. Its time tracks package count, not history: it barely moves across a 100× range of commits, because it isn't reading them. That cuts the other way too — most of every row where we beat it is npx and Node startup, not release planning. On 50 × 300 · graph, FerrFlow is slower than commit-and-tag-version because it's the only tool doing the job — resolving a 50-package dependency cascade and recovering missed releases across the history. The others emit one bump and have no notion of a dependency graph. We're fixing the fixtures (Fixtures#141); until then, read those two cells as a measurement gap, not a verdict.
  • 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 utilise tous les cœurs — 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 ms7 ms0.9×
Monorepo · 10 packages × 100 commits9 ms9 ms1.0×
Monorepo · 50 packages × 500 commits10 ms11 ms0.9×
Monorepo · 100 packages × 1k commits16 ms19 ms0.8×
Monorepo · 50 packages × 5k commits31 ms35 ms0.9×
Monorepo · 200 packages × 10k commits64 ms65 ms1.0×
Monorepo · dependency graph · 50 packages × 300 commits20 ms16 ms1.2×

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 commits7 ms3 ms2.6×
Monorepo · 10 packages × 100 commits9 ms3 ms2.8×
Monorepo · 50 packages × 500 commits11 ms3 ms3.7×
Monorepo · 100 packages × 1k commits18 ms4 ms4.5×
Monorepo · 50 packages × 5k commits36 ms3 ms12.3×
Monorepo · 200 packages × 10k commits65 ms3 ms19.0×
Monorepo · dependency graph · 50 packages × 300 commits18 ms4 ms4.5×

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
changesets26.0 MB
commit-and-tag-version9.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.