Skip to content

perf: add fast path for simple recursive globs#2884

Draft
Napolitain wants to merge 5 commits into
go-task:mainfrom
Napolitain:issue-2853-simple-glob-fast-path
Draft

perf: add fast path for simple recursive globs#2884
Napolitain wants to merge 5 commits into
go-task:mainfrom
Napolitain:issue-2853-simple-glob-fast-path

Conversation

@Napolitain

@Napolitain Napolitain commented Jun 18, 2026

Copy link
Copy Markdown

This is a stacked optimization PR on top of the filesystem benchmark work in #2881. Please review or merge #2881 first; this branch intentionally depends on those benchmarks so the performance impact can be evaluated with the same many-small and few-large fixtures.

This is independent from #2883.

This PR optimizes expansion for simple recursive source globs like path/to/folder/**/*.yaml.

The fast path only handles narrow literal-root recursive globs. More complex shell-style patterns continue to use the existing expander, and symlinked directories fall back to the existing path to preserve current behavior.

BenchmarkManySmallFiles/checksum-28                    3         389359224 ns/op           0.26 MB/s             0.09537 source_MiB/op     20000 source_files/op      2004835176 B/op   491402 allocs/op
BenchmarkManySmallFiles/timestamp-28                   3          83254561 ns/op           1.20 MB/s             0.09537 source_MiB/op     20000 source_files/op      42646077 B/op     311394 allocs/op
BenchmarkManySmallFiles/native-mtime-28                3          18549550 ns/op           5.39 MB/s             0.09537 source_MiB/op     20000 source_files/op      11558392 B/op     123036 allocs/op
BenchmarkManySmallFiles/none-28                        3            744356 ns/op         2598650 B/op       3193 allocs/op

BenchmarkFewLargeFiles/checksum-28                     3          60481191 ns/op        8876.66 MB/s           512.0 source_MiB/op            4.000 source_files/op    1064938 B/op       1551 allocs/op
BenchmarkFewLargeFiles/timestamp-28                    3            113883 ns/op        4714246.05 MB/s        512.0 source_MiB/op            4.000 source_files/op     262730 B/op       1525 allocs/op
BenchmarkFewLargeFiles/native-mtime-28                 3             11552 ns/op        46475623.60 MB/s               512.0 source_MiB/op             4.000 source_files/op      4701 B/op         44 allocs/op
BenchmarkFewLargeFiles/none-28                         3           1048155 ns/op         2573429 B/op       3185 allocs/op

Add Issue go-task#2853 benchmarks comparing checksum, timestamp, and uncached tasks across many-small and few-large sparse YAML source sets.

Baseline on Intel i7-14700K, go test -run '^$' -bench 'BenchmarkIssue2853.*SparseYAMLFiles' -benchtime=3x -count=3 ./

Many small sparse YAML files (20,000 x 5 bytes): checksum 440-451 ms/op, timestamp 140-148 ms/op, none 1.1-1.3 ms/op.

Few large sparse YAML files (4 x 128 MiB): checksum 60-61 ms/op, timestamp 213-239 us/op, none 1.1-1.3 ms/op.

Sparse files avoid bulk data writes while preserving logical file size for checksum/timestamp comparisons.
Add an OS-native mtime reference point for the Issue go-task#2853 filesystem benchmarks. The reference walks the same sparse YAML source tree with filepath.WalkDir, stats YAML files through DirEntry.Info, and compares mtimes against a generated output file.

The benchmark is available under the fsbench build tag alongside the Task checksum, timestamp, and uncached cases.
Rename the fsbench benchmark entry points from Issue-2853-specific names to BenchmarkManySmallFiles and BenchmarkFewLargeFiles.

The benchmark output is now easier to scan while the PR and commit history still carry the issue context. Helper and constant names were updated to match; benchmark behavior is unchanged.
Recognize simple literal-root recursive glob patterns such as path/to/folder/**/*.yaml and expand them with filepath.WalkDir plus filepath.Match. Patterns with complex shell features continue to use the existing mvdan shell expander, and symlinked directories explicitly fall back so existing recursive symlink behavior is preserved.

Many-small benchmark before this branch was about 420-450 ms/op checksum and 137 ms/op timestamp for 20,000 tiny files. After this change, repeated local runs measured about 386-391 ms/op checksum and 88-89 ms/op timestamp, with timestamp allocs dropping to about 311k/op.

Verification: go test ./...; go test -tags fsbench -run '^$' -bench 'BenchmarkManySmallFiles/(checksum|timestamp)$' -benchtime=5x -count=3 -benchmem ./
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