33e77a55 Andy McCall 1 month ago ↶
1
# Overnight backlog 3 (from 2026-09-29): not worse than Git
2
3
Andy's brief: there is no point making a tool that is worse than Git.
4
Until oxy matches Git on a real, large tree, this is the only work:
5
speed, memory and space at scale, with correctness never traded away.
6
7
Work top to bottom. An item is done when:
8
- its tests pass and the gate is clean;
9
- it is measured before and after on Earth, and the numbers are in
10
` docs/benchmarks.md` ;
11
- it is committed with ` oxy` as Andy and pushed to Earth.
12
13
If an item is too large, split it here and do the first part. Log each
14
iteration at the bottom.
15
16
## The yardstick
17
18
The Linux tip on Earth: 95 943 files, 1.8 GB, on 4 cores with 31 GiB.
19
Git 2.53 does this (from ` ~/bench/linux/results.txt` , 2026-09-29):
20
21
22
23
| First commit of the tree | 33.7 s, 42 MB | at most 50 s, under 2 GB |
24
| Clean ` status` (warm) | 0.26 to 0.31 s, 31 MB | at most 0.4 s, under 300 MB |
25
| ` status` , one file edited | 0.25 s | at most 0.4 s |
26
| ` diff` , one file edited | 0.34 s | at most 0.5 s |
27
| ` commit` , one file edited | 0.43 s | at most 0.6 s |
28
| ` status` , 1 000 files edited | 0.26 s | at most 0.5 s |
29
| ` diff` , 1 000 files edited | 1.38 s | at most 2 s |
30
| ` commit` , 1 000 files edited | 0.76 s | at most 1.2 s |
31
| ` log -n 100` | 0.05 s | at most 0.1 s |
32
| ` blame MAINTAINERS` | 0.07 s | at most 0.2 s |
33
| Checkout of another state and back | 0.49 s and 0.38 s | at most 1 s each |
34
| Store after gc | 311 MB (` .git` ) | at most 350 MB |
35
| Everyday commands | about 31 MB | under 300 MB |
36
37
The targets allow oxy a small margin, because it does more (conflicts
38
as data, signatures, an operation log). A target that turns out to be
39
out of reach for a structural reason is written up here, with the best
40
number reached and why. It is never quietly dropped.
41
42
## Rules for this loop
43
44
- ** Measure first.** Before changing code, measure where the time or
45
memory goes on Earth: ` /usr/bin/time -v` , ` perf record` (installed on
46
Earth), ` OXY_TIMING` phases, or a counting allocator behind a feature.
47
Record what the profile showed in the log.
48
- ** Heavy work only on Earth** , always under a cap:
49
` systemd-run --user --scope -p MemoryMax=14G …` . Andy's workstation has
50
crashed from memory before. Locally, run the gate and small cases only.
51
- ** Getting code to Earth.** ` ~/bench/oxygen` on Earth is a plain copy of
52
the source. Sync it with ` rsync -a --delete --exclude target --exclude
53
.oxy -e "ssh -i ~/.ssh/earth_claude" ~/development/oxygen/
54
claude@earth:bench/oxygen/` .
55
- ` ~/bench/linux-bench.sh` builds oxy from that copy and runs the whole
56
comparison. ` ~/bench/first-commit.sh` runs only the first commit,
57
status and fsck.
58
- Run long jobs with Bash ` run_in_background` , and wait for the
59
completion notice rather than polling.
60
- ** Correctness is never traded.** Every change keeps these passing:
61
` oxy fsck` on the Linux repository, the property tests, and
62
` oxy git verify` on the Git imports.
63
- ** Format changes** (change, checkpoint, pack or wire) are allowed
64
before 1.0, with these steps:
65
- bump the spec draft and keep old objects readable with unchanged
66
hashes;
67
- bump ` deps/oxygen` in oxygenflow with ` make pins` , gate, commit,
68
push and ` make deploy-runner` ;
69
- then ` make pins` in oxygenhub, gate, commit, push, ` make deploy` ,
70
and check ` /health` ;
71
- only then install the new oxy locally. Commit the format change
72
itself with the old binary.
73
- ** Memory and pace.** Every workstation build and test runs under
74
` systemd-run --user --scope -p MemoryMax=8G` , and
75
` CARGO_INCREMENTAL=0` (the disk is nearly full).
76
b9c2d543 Andy McCall 1 month ago ↶
77
## Correctness first (from metalgear, 2026-09-29)
78
79
A working copy that silently becomes the wrong tree is worse than any
80
slowness, so these come before everything else.
81
82
- [ ] C1 ** Working-copy writes hold the workspace lock** (oxygen#36). Checkout, bookmark switch (with --carry), pull's checkout, undo, discard and commit hold the lock from reading the head until their operation is recorded. ` merge_views` never lets a working-copy change based on a replaced one win. Test: a snapshot concurrent with a checkout never records the checkout's writes as edits.
83
- [ ] C2 ** ` bookmark create NAME CHANGE` refuses a partial state** (oxygen#37). When CHANGE is one of the current state's heads but not all of them, it refuses and explains, unless given --only. ` bookmark switch` summarises a wide tree difference. The guide explains that bookmarks name states, not ancestry.
84
- [ ] C3 ** A parent's switch never rolls a subrepo's bookmark back** (oxygen#38).
85
- [ ] C4 ** ` pull` says "Already up to date" while one behind** (oxygen#29). Reproduce it with a test, then fix it.
86
33e77a55 Andy McCall 1 month ago ↶
87
## Memory
88
89
- [ ] M0 ** Tools to see memory.** Add a counting global allocator behind
90
a cargo feature (peak bytes and allocation count per ` OXY_TIMING`
91
phase), so a profile names the structure that holds the memory. Then
92
profile a clean ` status` of the Linux repository, killed at 14 GB
93
(oxygen#35), and the first commit (9.9 GB). Write down which
94
structures hold what before changing anything.
95
- [ ] M1 ** Status without every graph** (oxygen#35). A clean ` status`
96
must not build every file graph. Unchanged files are skipped by the
97
manifest (spec §12.4), and the first status after a commit must not
98
replay the whole change. Options: the commit writes a checkpoint;
99
history-only states load graphs on demand (` State::load_graphs` ).
100
Target: under 300 MB and 0.4 s.
101
- [ ] M2 ** Lines without an allocation each.** An insert's lines become
102
one shared buffer with line offsets (for example ` Arc<[u8]>` and
103
ranges) in the change and in the file graph. The file graph shares
104
that buffer and does not copy it. ` AtomInfo` and the edge map shrink.
105
Measure bytes per line before and after.
106
- [ ] M3 ** A commit that streams.** The snapshot builder stores each
107
file's text blob as it reads it and keeps no content it no longer
108
needs, and the state is built without a second copy. Target for the
109
first commit: under 2 GB.
110
- [ ] M4 ** Everyday commands under 300 MB** on the Linux repository:
111
status, diff, commit, log and blame, one file and 1 000 files edited.
112
113
## Speed
114
115
- [ ] S1 ** First commit at most 50 s** (55.3 s now): profile with
116
` perf` , and parallelise reading, hashing and diffing across the four
117
cores where it is safe.
118
- [ ] S2 ** Status, diff and commit** with one and with 1 000 files
119
edited, to the targets above.
120
- [ ] S3 ** log, blame and checkout** on the Linux repository, to the
121
targets above.
122
- [ ] S4 ** fsck and gc** measured against Git's. Re-run Git's ` fsck`
123
with gc turned off: 451 s is suspect, because Git's own background gc
124
raced it.
125
126
## Space
127
128
- [ ] P1 ** Store at most 350 MB after gc** (442 MB now against Git's
129
311 MB): measure what takes the space (changes, text blobs, graphs,
130
checkpoints, indexes), then fix the largest. Compression level and
131
dictionary, and packing order, are all candidates.
132
133
## History at scale
134
135
- [ ] H1 ** Importer name conflict** (oxygen#30): the 5 000-commit
136
vscode import differs from Git in 51 files. Fix the cause and add a
137
test. ` oxy git verify` must be clean.
138
- [ ] H2 ** Import memory** : drop graphs untouched by recent commits and
139
reload them on demand, so memory is bounded by the working set and not
140
by the history.
141
- [ ] H3 ** Linux, stage 2** : import slices of recent history (2 000,
142
10 000 and 50 000 commits), each verified, then time log, blame and
143
status against Git on the same slice.
144
- [ ] H4 ** vscode's full history** (about 130 000 commits) into a scratch
145
repository on Earth. It is not published. Verify it and time it.
146
- [ ] H5 ** Linux's full history** (about 1.3 million commits) if H3 shows
147
it can finish overnight. Otherwise, write up what stands in the way.
148
149
## Finally
150
151
- [ ] Z1 Re-run the full ` ~/bench/linux-bench.sh` with the final build,
152
and put the complete Git against oxy table in ` docs/benchmarks.md` .
153
Summarise, for Andy, where oxy now matches or beats Git and where it
154
does not.
155
156
## Log
157
158
- 2026-09-29 Backlog written. Starting point: the Linux first commit
159
succeeds (55.3 s, 9.9 GB, 442 MB store) with change format 2
160
(oxygen#34). A clean ` status` is killed at 14 GB (oxygen#35).