Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Benchmark method

Principles

  • One build. Every number on the results page comes from the same release artifact. Results from different versions are never combined.
  • Exact output first. A timing counts only if Fastmash’s output matches the expected output for that job.
  • Same conditions. GNU datamash and Fastmash run on the same host, with the same input files and locale, and alternating order. Each invocation’s output is captured in files on the same filesystem and checked for equality. Input is redirected from regular files; piped input can perform differently.
  • Repeated sessions. Each job runs in two separate sessions, each with one warm-up and six measured repetitions, alternating the programs. We report medians and keep the minimum and maximum. Files are in the page cache (warm-cache measurements).
  • Resources as well as time. CPU time and peak charged memory (from cgroups) are recorded for every job.

Representative jobs

Jobs are grouped into job families, each representing a kind of work:

Job familyWhat it measuresExample job
StartupFixed per-process costA tiny input
Decimal accumulationParsing and summing many numbersSum and mean of a million decimals
Retained numerical summariesOperations that keep every valueQuantiles by group
Grouped numerical analysisGrouping with numerical operationsExon statistics by gene
Grouped text and countsGrouping with text operationsUnique values by key

Datasets include public real-world data (RefGene genome annotations, the UCI Wine Quality data) and generated data with controlled shapes. The benchmark kit runs eight of the core jobs with their exact arguments, downloads the public data and regenerates the synthetic inputs from the same fixed seed.

Acceptance rules

The rules are fixed before a release candidate is measured:

RuleThreshold
A job counts as a winAt least 20% lower median elapsed time and at least 5 ms saved per run, in both sessions and in at least five of six paired rounds
Fastmash is “faster” overallOn each host: wins in at least three of the four non-startup job families, including real-data wins in at least two; no unresolved material slowdowns; small commands within their limits
Material slowdownMedian elapsed time more than 10% and more than 5 ms longer
Small commandsAt most 5 ms slower than GNU datamash, and at most 20 ms in total
CPU slowdownMore than 20% and more than 5 ms extra CPU time
Memory reviewPeak memory more than twice GNU datamash’s and 64 MiB more

A job that fails, times out or gives a wrong answer counts as a failure, not a result. Each candidate is also compared with the previous accepted Fastmash build on every existing job (the predecessor guards); a slowdown beyond these limits needs an explicit, published justification.

Hosts

HostCPUOSglibcSystem sort
LaptopIntel Core i7-8550UCachyOS, native Linux 7.2.92.44GNU coreutils 9.12
DesktopAMD Ryzen 7 9800X3DCachyOS, native Linux 7.2.92.44GNU coreutils 9.12

GNU datamash’s -s jobs sort with the system sort, so its speed is part of their times.

Each complete command and its children run with a 512 MiB cgroup memory limit, no swap, at most 64 tasks (processes and threads), a 30-second timeout and a 512 MiB per-file output limit. Temporary files are on disk-backed Linux storage. Both programs get the same limits; Fastmash’s sort memory override is unset. These conditions matter for large sorts: the memory available to a command affects when it writes runs to disk. Separate, untimed observations confirm that the disk-spill and spill-large jobs write temporary runs on both hosts under these limits and still produce the expected output.

Full results

Mean of the two sessions’ median elapsed times, for every job and setting in the 0.1.0 measurement (release binary 1f1fec94…, 5 and 6 October 2026). Every job gave the expected output on both hosts. Sets: core and supplement are the representative jobs; locale-C, locale-en and locale-de repeat locale-sensitive jobs under C, en_US.UTF-8 and de_DE.UTF-8; guards are small edge-case jobs; the spill sets exercise larger sorts and their boundaries. CPU time and peak memory are in the measurement record. The displayed means average the retained session medians, already rounded to 0.1 ms, then round that mean to 0.1 ms. Ratios use the displayed values. Precise unrounded samples remain in the measurement record.

The elapsed verdict preserves each comparison’s two-session result. A regression crosses the material slowdown limits in both sessions, with Fastmash slower in at least five of six paired rounds in each. A threshold or direction disagreement is inconclusive; it does not establish a win or a competitive pass. Within margins means both sessions stay within the material regression limits. The named limitations retain the practical costs and uncertainty.

Intel laptop, native Linux

SetJobGNU datamash 1.9 (ms)Fastmash 0.1.0 (ms)GNU / FastmashElapsed verdict
coredecimal-10001.61.61.00×Within margins
coredecimal-10000036.814.62.52×Within margins
coredecimal-1000000324.7122.52.65×Within margins
coredisk-spill572.4694.10.82×Regression
coredominant-group21.911.91.84×Within margins
coregene-many160.4105.01.53×Within margins
coregene-tiny2.61.41.86×Within margins
coregenes-example7.33.81.92×Within margins
coregrouped-decimal-10000069.938.51.82×Within margins
corerefgene-exons159.483.11.92×Within margins
corerefgene-quantiles112.826.64.24×Within margins
corerefgene-transcripts112.061.01.84×Within margins
corescores-by-major2.61.41.86×Within margins
coretiny-count1.21.50.80×Within margins
coretiny-decimal1.21.50.80×Within margins
corewine-by-quality6.43.22.00×Within margins
corewine-red-summary1.71.61.06×Within margins
corewine-white-summary4.62.81.64×Within margins
disk-spilldisk-spill771.3773.51.00×Inconclusive
guardsdistinct-20000-geomean4.85.90.81×Within margins
guardsdistinct-200000-geomean37.444.80.83×Regression
guardsextreme-unique-1281.11.40.79×Within margins
guardsextreme-unique-200004.97.20.68×Within margins
guardsmissing-pairs3.01.81.67×Within margins
guardsmoments-all-10000069.929.62.36×Within margins
guardsmoments-alternating-10000069.852.81.32×Within margins
guardspaired-all-100000110.268.41.61×Within margins
guardssubnormal-unique-1281.11.70.65×Within margins
guardssubnormal-unique-2000010.68.81.20×Within margins
locale-Clocale-prepared22.124.90.89×Within margins
locale-Clocale-scientific41.830.61.37×Within margins
locale-delocale-prepared22.825.00.91×Within margins
locale-delocale-scientific104.130.73.39×Within margins
locale-enlocale-prepared22.625.00.90×Within margins
locale-enlocale-scientific104.230.53.42×Within margins
many-keysmany-keys780.3965.10.81×Regression
spill-guardsalternating-original304.527.011.28×Within margins
spill-guardsalternating-packed305.831.99.59×Within margins
spill-guardsgene-many160.6103.81.55×Within margins
spill-guardsrefgene-exons158.882.71.92×Within margins
spill-guardstiny-count1.11.30.85×Within margins
spill-guardswide-original440.961.27.20×Within margins
spill-guardswide-packed442.4219.82.01×Within margins
spill-halfspill-half297.6245.91.21×Within margins
spill-largespill-large1418.01079.11.31×Inconclusive
supplementbase64-10001.61.61.00×Within margins
supplementbase64-10000051.434.01.51×Within margins
supplementcross-dense40.736.21.12×Within margins
supplementcross-small2.51.41.79×Within margins
supplementcross-sparse5.23.81.37×Within margins
supplementextract-10002.01.81.11×Within margins
supplementextract-100000101.053.61.88×Within margins
supplementhash-10002.02.10.95×Within margins
supplementhash-10000093.382.71.13×Within margins
supplementmixed-10001.82.00.90×Within margins
supplementmixed-10000079.362.21.27×Within margins
supplementpath-10001.51.70.88×Within margins
supplementpath-10000043.033.81.27×Within margins
supplementrounding-10003.12.81.11×Within margins
supplementrounding-100000194.3130.91.48×Within margins
supplementtable-small1.11.40.79×Within margins
supplementtable-tall7.35.01.46×Within margins
supplementtable-wide5.74.71.21×Within margins
supplementwine-group-complete7.24.21.71×Within margins
supplementwine-group-prepared4.24.01.05×Within margins
supplementwine-means3.52.81.25×Within margins
supplementwine-moments4.03.01.33×Within margins
supplementwine-paired4.23.81.11×Within margins
supplementwine10-means25.714.61.76×Within margins
supplementwine10-moments31.017.21.80×Within margins
supplementwine10-paired32.525.01.30×Within margins

AMD desktop, native Linux

SetJobGNU datamash 1.9 (ms)Fastmash 0.1.0 (ms)GNU / FastmashElapsed verdict
coredecimal-10000.60.61.00×Within margins
coredecimal-10000010.95.32.06×Within margins
coredecimal-1000000105.946.82.26×Within margins
coredisk-spill180.0309.70.58×Regression
coredominant-group9.04.52.00×Within margins
coregene-many55.038.71.42×Within margins
coregene-tiny1.10.61.83×Within margins
coregenes-example3.01.61.88×Within margins
coregrouped-decimal-10000025.614.81.73×Within margins
corerefgene-exons62.236.51.70×Within margins
corerefgene-quantiles50.313.13.84×Within margins
corerefgene-transcripts45.626.51.72×Within margins
corescores-by-major1.00.52.00×Within margins
coretiny-count0.50.60.83×Within margins
coretiny-decimal0.50.51.00×Within margins
corewine-by-quality2.81.42.00×Within margins
corewine-red-summary0.60.61.00×Within margins
corewine-white-summary1.71.21.42×Within margins
disk-spilldisk-spill176.3311.60.57×Regression
guardsdistinct-20000-geomean2.12.40.88×Within margins
guardsdistinct-200000-geomean17.418.40.95×Within margins
guardsextreme-unique-1280.40.60.67×Within margins
guardsextreme-unique-200002.23.10.71×Within margins
guardsmissing-pairs1.40.81.75×Within margins
guardsmoments-all-10000022.411.12.02×Within margins
guardsmoments-alternating-10000024.220.11.20×Within margins
guardspaired-all-10000036.233.41.08×Within margins
guardssubnormal-unique-1280.40.80.50×Within margins
guardssubnormal-unique-200001.63.70.43×Within margins
locale-Clocale-prepared7.310.50.70×Within margins
locale-Clocale-scientific15.512.61.23×Within margins
locale-delocale-prepared7.610.50.72×Within margins
locale-delocale-scientific43.112.63.42×Within margins
locale-enlocale-prepared7.510.50.71×Within margins
locale-enlocale-scientific43.012.73.39×Within margins
many-keysmany-keys314.8405.90.78×Inconclusive
spill-guardsalternating-original97.78.511.49×Within margins
spill-guardsalternating-packed97.69.110.73×Within margins
spill-guardsgene-many55.138.81.42×Within margins
spill-guardsrefgene-exons62.536.51.71×Within margins
spill-guardstiny-count0.50.60.83×Within margins
spill-guardswide-original140.323.85.89×Within margins
spill-guardswide-packed141.996.31.47×Within margins
spill-halfspill-half95.3100.80.95×Within margins
spill-largespill-large263.1467.60.56×Regression
supplementbase64-10000.60.61.00×Within margins
supplementbase64-10000017.613.31.32×Within margins
supplementcross-dense16.614.41.15×Within margins
supplementcross-small1.10.61.83×Within margins
supplementcross-sparse2.21.61.38×Within margins
supplementextract-10000.80.71.14×Within margins
supplementextract-10000035.323.21.52×Within margins
supplementhash-10000.80.61.33×Within margins
supplementhash-10000038.915.12.58×Within margins
supplementmixed-10000.60.80.75×Within margins
supplementmixed-10000026.925.51.05×Within margins
supplementpath-10000.50.60.83×Within margins
supplementpath-10000015.212.61.21×Within margins
supplementrounding-10001.31.11.18×Within margins
supplementrounding-10000085.868.31.26×Within margins
supplementtable-small0.50.60.83×Within margins
supplementtable-tall2.32.11.10×Within margins
supplementtable-wide1.91.91.00×Within margins
supplementwine-group-complete3.01.91.58×Within margins
supplementwine-group-prepared1.61.70.94×Within margins
supplementwine-means1.31.11.18×Within margins
supplementwine-moments1.41.31.08×Within margins
supplementwine-paired1.51.60.94×Within margins
supplementwine10-means9.15.81.57×Within margins
supplementwine10-moments10.17.61.33×Within margins
supplementwine10-paired10.911.00.99×Within margins