Repository navigation
perf: globs over wide directories match without contending - #1522
Merged
Merged
Conversation
…n cores the walk leaves idle The implementations are stubs: every thread shares one regex, and judge_all spreads across every core however busy the walk keeps them.
…n cores the walk leaves idle
…thread skip-changelog: test only
8 tasks done
4 of 7 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Refs #1477
./*/*.mdover the depth-bound tree: 32 directories, each tens of thousands of entries wide. Two kinds of contention were inflating the judge phase (matching each entry against the glob):regex::Regexkeeps its match scratch in a pool shared by every thread. With 32 walk workers matching at once, threads other than the owner fight over sharded mutexes, and a thread that loses builds fresh scratch for a single match.PerThread<T>(per_thread.rs) gives each thread its own clone, andmatcher::Patternmatches through it.judge_allsplits a directory of 65536+ entries across every core, and it runs inside each of the walk's 32 workers, for up to about 1024 threads. The walk now counts its busy workers (tree_walk::busy_workers, which leaves out a worker waiting for a directory). A wide directory splits only acrossidle_cores(cores, busy), never fewer than one.Output is unchanged: byte-identical
SELECT path FROM './*/*.md'against main, md5 checked on the 3.2M-item tree.Measurements
These are paired medians, net of startup, as a ratio to
fdfind. The host ran at load 15-37 from concurrent agents, so expect a few percent of noise. The issue's 4.2x was not reproduced; main measures ~1.6x here../*/*.md(2.7M rows)./**/*.md, same tree (PerThread only)./*(single wide root)./*/*.md)Never splitting
judge_allmeasures 1.07-1.12 on the depth-bound tree, but regresses the mixed tree to 1.505. Splitting only across idle cores handles both shapes.Remaining levers (to reach <=1.0x)
Expected conflicts: #1480 rewrites
tree_walk::work(), and #1513 changes the signature ofscan_glob_rows.E2E Verification
packages/python/e2e-attestations/<branch>.jsonreceipt written ifpackages/pythonchanged (just e2e-attest-python)packages/ts/e2e-attestations/<branch>.jsonreceipt written ifpackages/tschanged (just e2e-attest-ts)cargo test --workspace --features clicd packages/python && uv run maturin develop --releasetesting-conventions e2e attest 'uv run python -m pytest tests/e2e/glob_speed_{depth_bound,one_level,recursive,matchers,dotfiles,gitignore,node_modules,symlink}_test.py tests/e2e/query_contract_test.py tests/e2e/fanout_test.py tests/e2e/use_case_join_test.py -q'cd packages/ts && testing-conventions e2e attest 'pnpm test:e2e'Changelog / Migrations
<root>/<pkg>/changelog.d/for each changed package (or:skip-changelogtrailer on a commit with reason)<root>/<pkg>/migrations.d/for each changed package (every subsection but Summary_None._when nothing breaks)