perf: reduce metadata syscalls in ScanDocumentationFiles - #3840
Open
Mpdreamz wants to merge 1 commit into
Open
Conversation
The original implementation performed up to 7 metadata operations per
file before producing a DocumentationFile:
f.Attributes × 2 (hidden + system check on the file)
f.Directory! × 2 (each call allocates a new IDirectoryInfo
wrapper and triggers its own stat)
f.LinkTarget × 1 (symlink check)
GetRelativePath × 2 (once in the filter, once in the final select)
Three changes:
1. Compute relative path once from the raw string returned by
EnumerateFiles — before IFileInfo allocation. This also moves the
dot-prefix hidden-folder check ahead of IFileInfo.New() so that
path-filtered files never get a wrapper allocated at all.
2. Consolidate the file-level Where into a single Attributes read per
file (the original read it twice via separate .Where() chains).
3. Cache directory-attribute lookups in a per-call dictionary keyed by
directory path. Directories are shared by many files; without the
cache each contained file allocated a fresh IDirectoryInfo and
triggered a redundant stat on the same directory.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
reakaleek
approved these changes
Aug 12, 2026
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.
Summary
ScanDocumentationFilesperformed up to 7 metadata operations per file before producing aDocumentationFile:f.Attributesf.Directory!IDirectoryInfowrappers + 2 stats (same dir re-stated per contained file)f.LinkTargetPath.GetRelativePathThree changes:
EnumerateFiles— beforeIFileInfo.New(). This also lets the dot-prefix hidden-folder check (StartsWith('.')) run with zero metadata syscalls; path-filtered files never get a wrapper allocated.Attributesread per file consolidates the two separate.Where()chains that each read it.Dictionary<string, FileAttributes>keyed by parent path avoids allocating a freshIDirectoryInfoand re-stating the same directory for every file it contains. Across 435k files in a large but finite directory tree, most directories are shared by many files.Test plan
dotnet test tests/Elastic.Markdown.Tests/ --filter NavigationTests|DocSet— 199 tests passdotnet test tests/Elastic.Markdown.Tests/— full 1951-test suite passesdotnet run --project src/tooling/docs-migrate -- bench— recordDocumentationSet ctortime🤖 Generated with Claude Code