Skip to main content
Version: Next

Benchmarks

What the code costs, as opposed to what it does and what the suite reached.

Measured on 2026-09-25 at commit 374e6469e43c, by the release that published this site.

This release measured 91 benchmarks across 3 modules, on linux/amd64, AMD EPYC 7763 64-Core Processor.

Every number on this page is measured rather than written. A benchmark pass runs go test -run '^$' -bench . -benchmem per module, in a stage of its own, and the release folds the stream into the same report the coverage and test-results pages read. Nothing here is a figure someone typed into a document, which matters more for a performance claim than for almost any other kind: a benchmark number written by hand is a number about a machine that no longer exists.

-run '^$' is not optional. Without it every test runs again alongside the benchmarks, and the timings become numbers about a machine that was busy doing something else. -benchtime is left at Go's own default, because a measurement taken over fewer iterations than the tool chose is a measurement nobody can compare.

The benchmark stages are cached by the module source, workspace providers and reporting tool they contain. A docs-only commit reuses the identical stream; a source, dependency or harness change runs the benchmark again. The report names the publishing commit while retaining the runner and timestamp recorded by the actual benchmark process.

By module​

pkg/ccme

linux/amd64, AMD EPYC 7763 64-Core Processor

BenchmarkTime/opBytes/opAllocs/opIterations
BenchmarkNormalizeFastPath102.3 ns0 B017,484,582
BenchmarkNormalizeRewrite742.6 ns240 B11,634,053
BenchmarkParseCRLF4.7 µs1.2 KiB5243,950
BenchmarkParseDirectives25.3 µs2.5 KiB1682,282
BenchmarkParseHistory36.4 µs9.5 KiB4232,644
BenchmarkParseInvalid7.6 µs1.3 KiB14153,630
BenchmarkParseMultiUnit13.2 µs3.8 KiB12127,032
BenchmarkParseParallel9.2 µs2.5 KiB16133,777
BenchmarkParseSimple6.9 µs1.2 KiB5338,930
BenchmarkParseSubject3.6 µs832 B2588,780

pkg/config

linux/amd64, AMD EPYC 7763 64-Core Processor

BenchmarkTime/opBytes/opAllocs/opIterations
BenchmarkApplyEdits/json1.5 ms18.7 KiB134690
BenchmarkApplyEdits/yaml3.8 ms407.7 KiB1,905495
BenchmarkDecode/fold-hit152.3 µs28.5 KiB54010,000
BenchmarkDecode/full163.2 µs28.4 KiB5147,282
BenchmarkDecode/small5.1 µs1.0 KiB22254,648
BenchmarkEnvBinding38.7 µs6.9 KiB13537,027
BenchmarkFold/lower15.94 ns0 B073,443,444
BenchmarkFold/mixed199.0 ns8 B111,018,461
BenchmarkFold/unicode505.8 ns16 B12,520,537
BenchmarkLoad151.5 µs20.3 KiB26512,180
BenchmarkOverrides63.7 µs12.2 KiB7218,942
BenchmarkReadTree/json/large2.8 ms413.0 KiB5,635583
BenchmarkReadTree/json/medium244.9 µs32.1 KiB5827,784
BenchmarkReadTree/json/small35.0 µs3.6 KiB7231,282
BenchmarkReadTree/toml/large8.3 ms681.7 KiB8,624145
BenchmarkReadTree/toml/medium406.0 µs54.7 KiB8823,462
BenchmarkReadTree/toml/small39.8 µs6.6 KiB10827,350
BenchmarkReadTree/yaml/large16.5 ms1.1 MiB19,626100
BenchmarkReadTree/yaml/medium973.3 µs106.9 KiB1,9991,416
BenchmarkReadTree/yaml/small133.0 µs16.8 KiB24410,000
BenchmarkRefDepth/167.4 µs4.9 KiB9345,309
BenchmarkRefDepth/32276.3 µs50.9 KiB6926,508
BenchmarkRefDepth/8142.0 µs15.1 KiB23210,000
BenchmarkRefWidth/219.5 µs3.6 KiB5859,533
BenchmarkRefWidth/32451.6 µs41.8 KiB6355,061
BenchmarkRefWidth/882.6 µs10.9 KiB17315,116
BenchmarkResolve/154.9 µs4.8 KiB5225,383
BenchmarkResolve/16337.3 µs17.8 KiB1743,674
BenchmarkResolve/4172.6 µs7.0 KiB765,832
BenchmarkSettings/dotted281.8 µs76.9 KiB5057,228
BenchmarkSettings/empty-objects56.8 µs6.6 KiB520,469
BenchmarkSettings/flat68.3 µs6.6 KiB528,621
BenchmarkSettings/nested73.3 µs11.7 KiB6519,395

services/dispat

linux/amd64, AMD EPYC 7763 64-Core Processor

BenchmarkTime/opBytes/opAllocs/opIterations
BenchmarkPolyrepoInitialVersionIndexes/100215.2 µs39.7 KiB2265,910
BenchmarkPolyrepoInitialVersionIndexes/10003.9 ms670.2 KiB2,050477
BenchmarkPolyrepoInitialVersionIndexes/1000018.4 ms5.3 MiB20,19657
BenchmarkPrintErrorDiagnostics70.3 µs0 B028,015
BenchmarkSetSnapshotPlanRepositoryClosures484.5 µs72.8 KiB263,421
BenchmarkSettleLinksExactFastPath2086.3 ms33.2 KiB3221
BenchmarkValidatePackageOwnership/1002.5 ms148.3 KiB1,613590
BenchmarkValidatePackageOwnership/100033.9 ms1.5 MiB16,02463
BenchmarkValidatePackageOwnership/10000347.3 ms15.1 MiB160,0843
BenchmarkFirstSnapshotToTwoNodes532.1 ms30.0 KiB2613
BenchmarkParseCommits275.5 ms72.3 MiB400,0319
BenchmarkParseControlGitlinkHistory124.6 ms41.0 MiB380,02214
BenchmarkParseTagsForPackagesIndexed/overlapping_custom_formats/indexed8.8 ms985.3 KiB8,919165
BenchmarkParseTagsForPackagesIndexed/overlapping_custom_formats/per_package_scan16.9 ms967.4 KiB8,90078
BenchmarkParseTagsForPackagesIndexed/standard_prefixes/indexed22.3 ms6.6 MiB71,02261
BenchmarkParseTagsForPackagesIndexed/standard_prefixes/per_package_scan1095.1 ms6.5 MiB71,1722
BenchmarkComputeChainTopology/packages=1024296.8 ms195.1 MiB632,3574
BenchmarkComputeChainTopology/packages=40964413.6 ms3277.6 MiB8,937,3011
BenchmarkComputeComposedSharedHistory46.1 ms16.2 MiB26,74922
BenchmarkComputeDependencyGraph/packages=102415.0 ms8.7 MiB41,03686
BenchmarkComputeDependencyGraph/packages=2564.0 ms1.9 MiB10,436277
BenchmarkComputeDependencyGraph/packages=409665.8 ms38.8 MiB163,58521
BenchmarkComputeFleetSnapshot/repositories=16/packages=25627.2 ms12.8 MiB118,86645
BenchmarkComputeFleetSnapshot/repositories=4/packages=647.3 ms3.4 MiB32,912165
BenchmarkComputeGroup/fixed5.7 ms803.9 KiB5,304236
BenchmarkComputeGroup/fixedMajor4.0 ms807.0 KiB5,304325
BenchmarkComputeGroup/fixedMajorMinor4.2 ms807.1 KiB5,304304
BenchmarkComputeGroup/fixedMajorSparse4.0 ms689.9 KiB3,689374
BenchmarkComputeGroup/fixedSparse3.7 ms689.9 KiB3,689304
BenchmarkComputeRealHistory/shape=bounded/commits=10000396.9 ms15.7 MiB76,3193
BenchmarkComputeRealHistory/shape=bounded/commits=500001469.6 ms83.5 MiB359,8291
BenchmarkComputeRealHistory/shape=composed/commits=10000603.7 ms34.3 MiB205,4172
BenchmarkComputeRealHistory/shape=composed/commits=500002528.4 ms183.4 MiB1,083,4031
BenchmarkComputeRealHistory/shape=whole/commits=10000752.7 ms46.5 MiB273,2132
BenchmarkComputeRealHistory/shape=whole/commits=500003250.0 ms227.2 MiB1,321,6981
BenchmarkComputeSharedHistory/packages=1284.0 ms1.9 MiB12,451279
BenchmarkComputeSharedHistory/packages=5127.3 ms3.2 MiB18,239168
BenchmarkComputeTagInventory/packages=256/versions=164.1 ms2.8 MiB9,813321
BenchmarkComputeTagInventory/packages=512/versions=84.5 ms2.4 MiB12,385254
BenchmarkComputeVersionGroups/groups=16/members=161.7 ms1.0 MiB5,613661
BenchmarkComputeVersionGroups/groups=64/members=167.5 ms4.3 MiB21,598156
BenchmarkControlCheckpointPersistentSnapshots1.1 ms452.4 KiB8,0321,008
BenchmarkControlWindows42.7 ms11.8 MiB80,26426
BenchmarkLinkBoundaryChain/repositories=2/depth=1109.4 µs43.5 KiB42210,000
BenchmarkLinkBoundaryChain/repositories=4/depth=3203.0 µs73.7 KiB8135,757
BenchmarkLinkBoundaryChain/repositories=8/depth=7442.1 µs138.9 KiB1,6712,486
BenchmarkReleaseRepositoryInputs973.2 µs424.4 KiB4,9761,230
BenchmarkCreateReleaseTags126.2 ms695.1 KiB7,6668

A row is one benchmark function, or one case of a table-driven one, named as its source names it. The iteration count is a column rather than a footnote because it is what says how much to trust the row beside it: a benchmark the tool ran ten times and one it ran ten million times are not the same kind of number. The machine is stated per module for the same reason. A nanosecond figure without the CPU that produced it is a number nobody can compare anything to, and a release runner is not a workstation.

Allocations are the figure to read first. A time depends on the machine, the toolchain and whatever else was running; an allocation count is a property of the code, and it moves only when someone changes what the code does. That is why several of these packages pin their allocation counts as tests, with a budget that has one allocation of headroom, so a toolchain change does not fail a build for a rounding difference while a reintroduced copy fails it immediately.

Fuzz targets​

TargetPackageCorpus entries
FuzzNormalizepkg/ccme114
FuzzParsepkg/ccme116
FuzzParseSubjectpkg/ccme114
FuzzParserspkg/config9
FuzzRefTargetspkg/config8
FuzzSettingspkg/config5
FuzzGradleLinepkg/scanner16
FuzzPBXSettingpkg/scanner9
FuzzParseAquaBoundedpkg/scanner1
FuzzParserspkg/scanner39
FuzzPep508Deppkg/scanner8
FuzzPodDeclarationpkg/scanner12
FuzzPodspecStatementpkg/scanner10
FuzzLinkpkg/writer12
FuzzReplaceBytespkg/writer8
FuzzRewriteAndroidManifestpkg/writer7
FuzzRewriteAquaNeverCommitsInvalidYAMLpkg/writer3
FuzzRewriteCargopkg/writer8
FuzzRewriteComposepkg/writer9
FuzzRewriteComposerpkg/writer6
FuzzRewriteCsprojpkg/writer6
FuzzRewriteDockerfilepkg/writer9
FuzzRewriteGemfilepkg/writer6
FuzzRewriteGodotCfgpkg/writer10
FuzzRewriteGradleBuildpkg/writer8
FuzzRewriteGradleCatalogpkg/writer8
FuzzRewriteMavenpkg/writer7
FuzzRewriteNpmpkg/writer8
FuzzRewriteNuGetListspkg/writer6
FuzzRewriteNuspecpkg/writer6
FuzzRewritePlistpkg/writer8
FuzzRewritePodfilepkg/writer8
FuzzRewritePubspecpkg/writer6
FuzzRewritePyprojectpkg/writer9
FuzzRewriteUPluginpkg/writer8
FuzzRewriteUnityProjectSettingspkg/writer8
FuzzRewriteXcodeProjpkg/writer7

A fuzz target under a plain go test runs its corpus rather than fuzzing: the seeds the test declares with f.Add, plus whatever testdata/fuzz holds for it: inputs earlier fuzzing sessions found interesting and kept as regression cases. The corpus column is what every suite run exercises, and it is the honest half of the number. It is not a claim that a fuzzing session ran here, because none did.

Fuzzing itself is a thing somebody does on purpose, for as long as they have:

go test ./... -run '^$' -fuzz FuzzParse -fuzztime 10m

A crash it finds is written into testdata/fuzz as a new corpus entry, committed, and from then on every run of the ordinary suite replays it. That is why the corpus grows and why the count above is worth reading: it is the number of inputs the suite is holding the parsers to, not the number of inputs anyone has tried.

Reproducing​

The whole measurement is one command per module from the monorepo root, and it is the one the release runs:

go run github.com/yohimik/dispat/tools/testreport bench config -- ./... -run '^$' -bench . -benchmem
go run github.com/yohimik/dispat/tools/testreport build # writes packages/docs/data/report.json, read by this page

The stream lands in coverage/benchlog/<module>.json, beside the go test -json logs the suites leave in coverage/testlog/. A module measured by a run replaces whatever it had; a module the run did not measure keeps it, so a release that rebuilt only part of the monorepo does not blank a page. Rebuilding this site with packages/docs/data/report.json in place is what puts the figures back; without one, the prose stays and the tables are left out.

What a benchmark here is for​

These are regression gates, not marketing. A benchmark exists in this repository when there is a specific mistake it would catch: a second deep copy of a parsed document, a flat intermediate map materialised only to be rebuilt, a per-element allocation in a loop that could have hoisted it. The corresponding allocation budget is what turns the benchmark into a gate. The benchmark says what it costs, and the budget fails the build when the cost changes for a reason nobody intended.

What none of them are is a comparison against another library. A benchmark measuring two things measures the harness between them, and this repository has no honest way to run somebody else's code on the same terms.