Skip to content

bench: fit the anchor tree to vscode's node_modules, 4 KiB files - #38

Closed
markovejnovic wants to merge 2 commits into
bench/fixture-namesfrom
bench/vscode-shape
Closed

markovejnovic wants to merge 2 commits into
bench/fixture-namesfrom
bench/vscode-shape

Conversation

@markovejnovic

Copy link
Copy Markdown
Owner

Stacked on #36.

Summary

The anchor tree (585 dirs × 100 empty files) was just mktree's defaults; nothing backed calling it a typical node_modules. I measured real ones (npm ci --ignore-scripts, macOS arm64, 2026-09-28):

project dirs files files/dir files ≤ 4 KiB
express 134 601 4.5 81%
vite react-ts 94 676 7.2 61%
insomnia 7de40fe 1,995 16,514 8.3 78%
create-next-app 16.3.6 2,056 21,394 10.4 76%
CRA 5.0.1 4,668 38,069 8.2 84%
vscode c17dab9 5,538 39,966 7.2 77%
jitsi-meet 852b61c 10,683 81,691 7.6 80%
bitwarden/clients bac4c66 13,331 124,430 9.3 83%
old anchor 585 58,500 100 — (all empty)

Every real tree has ~7–10 files per dir (the anchor had 100, so it underweighted directory work ~12×), ~2.7 subdirs per non-leaf dir, and median file size ~1 KiB. No real tree is empty files: APFS and ext4 give each small file one 4 KiB block to free.

The trees, all 4 KiB files except the 1 MiB one:

was now tree
balanced-58k balanced-38k anchor: vscode's shape made uniform, fanout 4, depth 6, 7 files per dir (5,461 dirs)
wide-51k wide-38k the anchor's 5,461 dirs and 38,227 files at one level
deep-58k deep-36k 11-level binary tree, 4,095 dirs × 9 files
balanced-58k-4kib — removed: the anchor is 4 KiB now
large-1mib-files unchanged
tiny-125 tiny-125 now 4 KiB files
balanced-333k balanced-152k the anchor one level deeper (monorepo sized; 333k × 4 KiB would write 1.3 GB per run)
flat-58k flat-38k the anchor's file count in one directory

A uniform tree isn't a perfect fit: 75% of its dirs are leaves (vscode: 63%), and files sit deeper. Good enough for a synthetic benchmark.

Bencher: new names again, so new series. README: its charts and "58,500-file tree" come from the old trees and need a new full run.

Test plan

  • ruff check, ruff format --check, 36 bench unit tests (one fewer fixture)
  • --bench=full collection lists the new ids
  • mktree builds each new tree (except the unchanged 1 MiB one) with exactly the expected dir and file counts (≤ 4 s each)
  • A benchmark run on the new trees

F0..F7 said nothing: reading a result meant looking the id up in
registry.py. Each id now names the tree's shape and file count
(balanced-58k, wide-51k, deep-58k, balanced-58k-4kib, large-1mib-files,
tiny-125, balanced-333k, flat-58k). That's what pytest ids, chart file
names and Bencher benchmarks show: demo/balanced-58k/warm/remmy@4. A test
keeps each id's file count in step with its tree.

Trees, tools, sampling and the decision rule are unchanged.
The anchor (585 dirs x 100 empty files) was mktree's defaults, with no
source for calling it typical. Measured eight real node_modules trees
(express to bitwarden/clients): every one has ~7-10 files per dir, not
100, and ~80% of files are <= 4 KiB, so each frees one block; none are
empty.

The anchor is now vscode's shape made uniform: fanout 4, depth 6, 7
files per dir (5,461 dirs, 38,227 files; vscode c17dab9 has 5,538 and
39,966). Every small-file tree uses 4 KiB files. The trees that vary one
thing of the anchor follow it: wide-38k keeps its dirs and files at one
level, flat-38k its file count in one dir, deep-36k a similar count.
The huge tree is the anchor one level deeper (152k files, monorepo
sized) instead of 333k, which at 4 KiB would write 1.3 GB per run.
balanced-58k-4kib is gone: the anchor is that now.
@markovejnovic

Copy link
Copy Markdown
Owner Author

Folded into #36: this commit (306fc35, cherry-picked unchanged) is now on top of #36's rebased branch, so both land as one PR.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant