OXYGENHUB

Benchmarks: the second round on the Linux tree (refs #41) e82591ec33a4

Author
Andy McCall @andymccall <[email protected]>
When
· 2026-09-30 23:00 UTC
Signature
✔ signed by Andy McCall
Hash
e82591ec33a43573338641ae9113f0fecbf2d3b5f584360e797cdf1805ce29e1
Depends on
1d360c91a289 61e9ad6ddc2d bd9414401fdc
Depended on by
cd19603782bf 72215f29df4c
In bookmarks
agents-in-readme bare-hashes carried-not-removed carry-identical doctor-trust identical-sides keyless-tags main merge-remote-bookmark only-help-103 paths-for-resolutions-and-amend push-notes show-stat subrepo-pin-state switch-says
In tags
v0.10.0 v0.11.0 v0.2.0 v0.3.0 v0.3.1 v0.4.0 v0.4.1 v0.4.2 v0.4.3 v0.4.4 v0.4.5 v0.4.6 v0.5.0 v0.5.1 v0.6.0 v0.7.0 v0.8.0 v0.9.0
Edits
2 atoms, 0 tree operations, 2 files

Browse the tree at this change

modified docs/backlog-overnight-4.md +2 −0
…
117 unchanged lines
118 118
- 2026-09-30 **B0** baseline (table in `docs/benchmarks.md`; `linux-bench.sh` now runs three of each, alternating, plus a local clone; the loop-3 script is kept as `linux-bench.sh.loop3`). oxy is ahead on the first commit (33.3 s against 38.2 s) and gc (48 s against 100 s); clean status is close (0.43 to 0.53 s against 0.34 to 0.46 s). Behind: dirty status and diff (1.5 to 2.2 s against 0.3 to 0.8 s), commit (2.5 to 3.1 s against 0.4 to 0.5 s), log (0.9 s against 0.00 s), blame (1.0 s against 0.07 s), checkout (3 s against 0.4 to 0.5 s), fsck (24 s against 13 s), and a new gap: a local clone takes 56 s and 3.3 GB against Git's 18 s. The store after gc is 375 MB (it now includes the 48 MB state index) against 295 MB.
119 119
120 120
- 2026-09-30 **S1, first round** (commits c9dca9ed to 077e899b; table in `docs/benchmarks.md`). A lister of our own replaces the ignore crate's walker (listing 0.5 s to 0.18 s); the manifest is a flat binary file with hashes and graph keys as bytes; the state index keeps each file's history encoded until used (a writer bug I made on the way was caught only on Earth, since a failed index read falls back to a full load: test builds now read every index written back); maps are built in path order; mimalloc is the allocator. Clean status is now ahead of Git (0.18 s against 0.22 s), the first commit too (24.4 s against 36.2 s), and gc (29.9 s against 70.3 s). One-file status is 0.47 s against 0.22 s. Log (S3, first part): metadata from the state index and a store cache, signature marks without reading changes: 0.20 s, of which 9 ms is the log. For Andy: `oxy log` checks the working copy first (about 0.18 s here); Git's log does not look at it. Dropping that check would make log about 20 ms, but the working-copy line would then show the last snapshot's state.
121 +
122 +
- 2026-10-01 00:00 **Second round** (6359f779 to 81a5bdd7; table in `docs/benchmarks.md`). Commit 0.67 s (from 0.96 s): the state index is brought up to date by replaying and rewritten only 16 changes behind; keys only for changed paths; attributes from the snapshot rather than a tree walk; the manifest checksummed and written without fsync; and a fix: after a status had seen an earlier edit, a commit kept that edit's stat in the manifest, so every later status took a full snapshot. Blame 0.16 s (from 0.59 s; Git 0.07 s), log 0.18 s, checkout 0.74 s each way (from 1.4 s) with two state indexes kept per workspace, and status right after a checkout that wrote 1 000 files 0.18 s (from 1.3 s). **R1** done: `oxy rebase --into-working-copy` (closes #42).
modified docs/benchmarks.md +32 −0
…
667 unchanged lines
668 668
150 ms (the syscalls alone: `find` with a stat of each file takes 0.37 s
669 669
on one core), loading the state index about 60 ms, reading the manifest
670 670
about 40 ms, rendering and diffing the changed file about 100 ms.
671 +
672 +
### S1 to S5, second round (2026-09-30 23:54, oxygen#41)
673 +
674 +
After the second round: merge joins over whole-tree maps, a commit that
675 +
works out keys only for what it changed and brings the state index up to
676 +
date by replaying rather than rewriting it, the manifest checksummed and
677 +
written without fsync, log and blame from the state index, checkout
678 +
through the index with two indexes kept. Load average 4.2 at the start,
679 +
no Flow jobs.
680 +
681 +
| Operation | oxy | 22:39 | Git |
682 +
|---|---:|---:|---:|
683 +
| init and commit the tip | **21.9 s**, 3.2 GB | 24.4 s | 33.7 s |
684 +
| status, clean | **0.17 to 0.19 s** | 0.17 to 0.18 s | 0.22 s |
685 +
| status, one file | 0.40 to 0.41 s (1.10 s first) | 0.47 s | 0.22 to 0.24 s |
686 +
| diff, one file | 0.39 to 0.48 s | 0.47 to 0.51 s | 0.10 to 0.11 s |
687 +
| commit, one file | 0.67 s | 0.96 s | 0.21 s |
688 +
| status, 1 000 files | 0.58 to 0.65 s | 0.65 s | 0.23 to 0.24 s |
689 +
| diff, 1 000 files | 0.59 to 0.62 s | 0.65 s | 0.46 to 0.48 s |
690 +
| commit, 1 000 files | 0.88 s | 1.20 s | 0.48 s |
691 +
| log -n 100 | 0.17 to 0.19 s | 0.48 to 0.53 s | 0.00 s |
692 +
| blame MAINTAINERS | 0.16 s | 0.59 s | 0.07 to 0.16 s |
693 +
| clone, local path | 32.2 s, 3.6 GB | 36.7 s | 17.0 s |
694 +
| checkout the first state, and back | 0.74 s, 0.74 s | 1.48 s, 1.37 s | 0.37 s, 0.33 s |
695 +
| fsck | 13.6 s | 14.0 s | 12.6 s |
696 +
| gc | **29.4 s** | 29.9 s | 70.2 s |
697 +
| store after gc | 369 MB | 369 MB | 295 MB |
698 +
699 +
The first one-file status after the first commit (1.10 s) builds the
700 +
state index for the first time. Most of what remains in status is listing
701 +
the tree (about 135 ms), loading the index (about 60 ms) and starting up;
702 +
commit adds storing and recording with fsync (about 100 ms).