grit://cooking/dogfood← what’s cooking
Wednesday, October 28, 2026 · Windows 11 Pro 10.0.26200

Dogfood on win-x64: Tool builder on grit-lib

5 repos · 27 commands · 5 broken · 4 slow · 5 filed

Played a Rust tool builder on win-x64: a fresh cargo project linking grit-lib by path (walk, tree sizes, status, blame, stage/commit, ref CAS, push with cancel, merge matrix, multi-thread and soak runs), compared against system git 2.55 and the grit CLI. All six 'fixed' issues re-checked as fixed on main 7071b20; the lib is fast and its typed writer/ref APIs are solid, interop with git 2.55 (reftable, sha256, MIDX, bitmaps, commit-graph) is clean. Filed 5 new issues: reserved-name loose refs on Windows (#2257), unvalidated symbolic ref targets (#2258), CRLF merge divergence from git (#2259), lossy blame content (#2260), spurious 'Access is denied' under in-process commit contention (#2261).

os
Windows 11 Pro 10.0.26200 · x86_64
machine
win-x64 self-hosted worker (Intel i5-12400, 12 threads, 16 GB RAM, NTFS)
versions
grit grit 0.5.23 (built from main) · main 7071b202 · git version 2.55.0.windows.5 (system gitconfig has core.autocrlf=true, core.symlinks=false)
repositories5
repofilescommits.gitnotes
rust-lang/cargo3,07823,59188 MBgit clone with CRLF worktree via system autocrlf
octocat/Hello-World130 MB
scratch/48k-files48,00049 MBbuilt with git fast-import, 400 dirs x 7 subdirs
scratch/grit-clone-of-cargo3,07823,59189 MBmade with grit clone; also used for gc/midx/bitmap/commit-graph
scratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———small purpose-built repos
commandsgrit vs. system git, wall time
commandrepogritgitgrit/gitresultnotes
lib: rev_walk().walk(HEAD) + read_commit x23.6krust-lang/cargo331 ms252 ms1.3×okgit = rev-list HEAD only (no commit parsing)
lib: tree walk with read_info sizesrust-lang/cargo16 ms57 ms0.3×okgit = ls-tree -r -l HEAD
lib: porcelain::status::statusrust-lang/cargo150 ms148 ms1.0×ok
grit statusscratch/grit-clone-of-cargo120 ms50 ms2.4×ok2.4x git, under the 3x bar; duplicate #1702
grit add . (clean)scratch/grit-clone-of-cargo179 ms46 ms3.9×slow3.9x git; duplicates #1682/#1702
lib: porcelain::add::stage (clean)scratch/grit-clone-of-cargo168 ms46 ms3.7×slow3.6x; duplicate #1682
grit add . (clean)scratch/48k-files226 ms71 ms3.2×slow3.2x; duplicate #1682
lib: porcelain::add::stage (clean)scratch/48k-files350 ms71 ms4.9×slow4.9x git, 1.5x slower than the CLI path; stat_refreshed=false and no speed-up on repeated runs; duplicate #1682
grit status (clean / 1 modified)scratch/48k-files150 ms71 ms2.1×ok2.1x
grit commit (1 file edited)scratch/48k-files332 ms112 ms3.0×ok3.0x; duplicate #1884
lib: create_commit (staged)scratch/48k-files114 ms——ok
lib: blame_file (Revision / Worktree)rust-lang/cargo123 ms172 ms0.7×oksrc/bin/cargo/cli.rs; other files 92-145 ms vs git 113-175 ms
lib: changelog over 123 tag rangesrust-lang/cargo280 ms3.93 s0.1×okgit = 123 rev-list --count processes; counts identical
lib: Remote::push (path, full cargo)rust-lang/cargo7.63 s4.80 s1.6×ok1.6x; git peak RSS not measurable (child process)
lib: Remote::push over smart HTTP (grit serve)rust-lang/cargo6.11 s3.78 s1.6×ok1.6x
lib: Remote::push cancelled at 300/500 msrust-lang/cargo300 ms——okCancelled returned on time, nothing left in destination
grit clone <local cargo>rust-lang/cargo1.29 s1.23 s1.0×ok
grit clone over smart HTTPrust-lang/cargo4.75 s5.98 s0.8×ok
grit fetch (20 new commits, HTTP)rust-lang/cargo98 ms680 ms0.1×ok
grit gc repack --bitmaps / midx / commit-graphscratch/grit-clone-of-cargo3.94 s——ok1943 + 125 + 1874 ms; git 2.55 fsck/multi-pack-index verify/commit-graph verify/bitmap rev-list all clean
grit init --ref-format reftable|--object-format sha256 + commit + gcscratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———okread by git 2.55; reverse via lib also ok
lib: commit_ref_update_on_store matrix (files + reftable)scratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———wrongsymref targets and log_only entries unvalidated #2258; aux ref #2257
grit branch aux / com1scratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———wrong#2257: git log --all fatal afterwards
grit merge (20-scenario matrix) vs git merge-tree --write-treescratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———wrong18/20 match; CRLF-vs-edit diverges #2259
lib: create_commit x 4-8 threadsscratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———errorspurious Access denied #2261
lib: 150-iteration soak (walk+status+write)rust-lang/cargo16.80 s——okflat working set
grit blame --json (latin-1 file)scratch/misc (merge matrix, locks, refs, reftable/sha256, unicode path)———wronglossy content, no flag #2260
worked7
  • ›Lib entry points (Repository::discover with RepositoryOptions::from_process, objects(), references(), rev_walk(), index_handle()) are discoverable and documented with doctests; no printing or exiting from the lib
  • ›Typed errors: RefStoreError::{ExpectedMismatch,MissingObject,NotACommit,NameUnavailable,LockHeld}, Error::Cancelled, InvalidTreeEntry are matchable
  • ›Walk/tree/blame performance is better than git per task (changelog 14x faster than process-per-range git); memory flat across a 150-iteration soak
  • ›Interop with git 2.55: reftable, sha256, MIDX, bitmaps, commit-graph written by grit verify cleanly; git-made reftable/sha256 repos usable through the lib
  • ›Push cancel (path and smart HTTP) returns promptly and leaves nothing behind; fixed issues #2176 #2178 #2180 #2106 #2177 #2107 all verified
  • ›Windows: locked files, read-only files, case-only rename, unicode/space paths, \\?\ and forward-slash repo paths, hooks via sh, worktrees, system autocrlf all fine
  • ›Merge matrix: rename/rename 1to2 (#1878), directory renames (#2179), file/dir, binary, adjacent hunks, clean trees all match git; identical-content parallel Odb::write now succeeds (#1875 looks fixed)
problems9
  • ›#2257 loose refs named aux/com1 created on Windows are unreadable by git (git log --all fatal, fsck errors)
  • ›#2258 RefStore transactions accept HEAD -> 'foo', self-referential symrefs and log_only reflog entries with missing objects; HEAD -> foo makes git say 'not a git repository'
  • ›#2259 CRLF-converted file + edit merges clean with mixed line endings where git conflicts
  • ›#2260 blame_file content is a lossy String with no raw bytes/flag (diff has encoding_lossy)
  • ›#2261 in-process concurrent create_commit yields 'insufficient permission ... Access is denied' on index/ref lock rename (no retry)
  • ›Not filed: add/stage/status on clean trees 2-5x slower than git on Windows, lib stage() slower than CLI and never refreshes the index so repeat runs stay slow (duplicates #1682/#1702/#1884)
  • ›Not filed (API polish): RevListOptions argv-shaped flag bag and not at revwalk::; two NewCommit types; two progress traits (ProgressSink vs remote::fetch::Progress); Signature requires the time crate which is not re-exported; BlameCommitInfo.author is a raw ident string; grit-lib as path dep emits 8 dead-code warnings; StageOptions has doc(hidden) 'integration tests only' fields
  • ›Not filed: file/dir merge conflict path suffix is the full commit id instead of the branch name (cosmetic); write_tree does not check mode against the entry's object type (documented as mktree --missing style); lib push peak RSS 261 MB for an 80 MB pack
  • ›Not filed: LockHeld/ExpectedMismatch from commit_ref_update_on_store: callers must handle two error kinds for a plain CAS loss under contention (1 in ~600 attempts returned LockHeld instead of ExpectedMismatch); mixed separators in lock-file error text
bugs filed5
#2257 #2258 #2259 #2260 #2261already reported: #1682 #1702 #1884 #1878 #2179 #1875 #1812 #2198 #2191 #1746
next time
  • ›Retry the Access-denied race with a separate process holding the index open (editor integration polling status while the CLI commits) and with an antivirus-like reader; check whether status refresh writes race with commit
  • ›Reftable and files backends under many writers with fault injection (kill -9 style) on Windows; stale .lock cleanup and recovery from a killed lib process
  • ›Pluggable ODB/RefStore toy backend run through porcelain on Windows (#2187, #2128, #2131 still open), and fsmonitor/untracked-cache watcher-driven status through the public API
  • ›Hours-long soak mixing fetch, gc and status with RSS tracking, 100+ writers
  • ›Criss-cross merges beyond the single-base example (#2114) and merge.directoryRenames config with conflicts through the CLI continue/abort flow
  • ›Blame -C copy detection / --ignore-revs on real histories and rename following on git/git (not reached here); also lib blame with Contents buffers containing CRLF under autocrlf=true
  • ›Re-test the merge EOL divergence under merge.renormalize / .gitattributes eol settings once #2259 is fixed
  • ›Smart HTTP receive-pack policy (denyNonFastForwards, hideRefs, fsckObjects) driven from the lib; push of 100k refs