Skip to content

fix: optimize glob pattern expansion to avoid full recursive directory traversal#501

Merged
fansenze merged 1 commit intomainfrom
fix/glob-perf-20260311
Mar 11, 2026
Merged

fix: optimize glob pattern expansion to avoid full recursive directory traversal#501
fansenze merged 1 commit intomainfrom
fix/glob-perf-20260311

Conversation

@fansenze
Copy link
Copy Markdown
Contributor

@fansenze fansenze commented Mar 11, 2026

Summary

PR #493 introduced glob pattern support for parserOptions.project in rslint.json. However, the walkProjectFiles implementation recursively traversed all directories (including node_modules) regardless of the glob pattern's actual depth requirement. For a pattern like ./packages/*/tsconfig.json, this caused ~4,000 unnecessary directory accesses instead of only checking the 8 direct children of packages/.

This PR replaces the hand-rolled recursive walk with doublestar.GlobWalk, which natively understands glob semantics (* = one level, ** = recursive) and only traverses directories as deep as the pattern requires. A vfs.FSfs.FS adapter (vfsAdapter) is introduced so that doublestar.GlobWalk can operate on the custom VFS interface used throughout the project.

The adapter also includes symlink cycle detection via realpath comparison in ReadDir, preventing infinite recursion when symlinks create directory cycles (e.g., packages/ui/loop -> packages).

Before (v0.2.2): linted 242 files in 1.56s
After: linted 242 files in 448ms (~3.5x faster on this repo; larger monorepos with deeper node_modules will see even greater improvement)

Test Coverage

  • Glob patterns: *, **, ?, [0-9], [!a]
  • Edge cases: non-existent search root, no matches, deduplication, mixed glob/non-glob paths, single * not matching nested dirs
  • VFS adapter: Open (root/directory/file/not-exist), ReadDir (all/paginated/exhausted), DirEntry metadata
  • Symlink cycle detection: verified cycle is broken after first traversal
  • Overlay VFS integration

Related Links

Checklist

  • Tests updated (or not required).
  • Documentation updated (or not required).

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request significantly improves the performance of glob pattern expansion within the configuration loading process. Previously, the system would unnecessarily traverse all directories, including large node_modules folders, even when a glob pattern specified a limited depth. By integrating the doublestar.GlobWalk library and providing a compatibility layer for the virtual file system, the directory traversal is now intelligently limited to only the paths required by the glob pattern, leading to a substantial reduction in linting time, especially in monorepos.

Highlights

  • Performance Optimization: Optimized glob pattern expansion for parserOptions.project in rslint.json by replacing an inefficient recursive directory traversal with doublestar.GlobWalk, resulting in a ~3.5x speed improvement.
  • Glob Pattern Handling: The previous custom walkProjectFiles function, which recursively traversed all directories (including node_modules), has been replaced with doublestar.GlobWalk which correctly interprets glob semantics (e.g., * for single-level, ** for recursive) to avoid unnecessary directory accesses.
  • Virtual File System Adapter: Introduced a vfsAdapter to bridge the project's custom vfs.FS interface with the standard io/fs.FS interface, allowing doublestar.GlobWalk to operate seamlessly within the existing virtual file system.
  • Test Coverage: Added new tests to validate the correct behavior of single-star glob patterns, handling of non-existent search roots, and the globSearchRoot utility function.
Changelog
  • internal/config/loader.go
    • Updated glob pattern expansion logic to use doublestar.GlobWalk for more efficient and accurate matching.
    • Removed the custom walkProjectFiles recursive directory traversal function.
    • Added an io/fs import to support the new glob walking mechanism.
  • internal/config/loader_test.go
    • Added TestLoadTsConfigsFromRslintConfig_SingleStarDoesNotMatchNested to verify correct single-star glob behavior.
    • Included TestLoadTsConfigsFromRslintConfig_NonExistentSearchRoot to test error handling for non-existent directories.
    • Introduced TestGlobSearchRoot with various patterns to ensure the search root calculation is accurate.
  • internal/config/vfs_adapter.go
    • Added a new file defining the vfsAdapter struct and its methods to implement the io/fs.FS interface over the project's vfs.FS.
    • Implemented vfsDirFile, vfsRegFile, vfsDirEntry, and vfsFileInfo to provide necessary io/fs interfaces for directory and file operations.
  • internal/config/vfs_adapter_test.go
    • Added a new file containing comprehensive unit tests for the vfsAdapter to ensure its correct functionality when opening files and directories, handling non-existent paths, and reading directory entries.
Activity
  • Tests were updated to cover the new glob pattern expansion logic and the vfsAdapter.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request effectively addresses a performance issue with glob pattern expansion by replacing a manual recursive directory walk with the more efficient doublestar.GlobWalk. However, the new implementation removes the symlink cycle detection that was present in the original code, which could lead to infinite recursion and Denial of Service when processing malicious or misconfigured directory structures. Additionally, there is a minor deviation from the io/fs.ReadDirFile interface contract in the new vfsAdapter.

…y traversal

Replace hand-rolled walkProjectFiles with doublestar.GlobWalk, which
natively understands glob semantics (* = one level, ** = recursive) and
only traverses directories as deep as the pattern requires.

Introduce a vfs.FS → fs.FS adapter (vfsAdapter) so doublestar.GlobWalk
can operate on the custom VFS interface. The adapter includes symlink
cycle detection via realpath comparison in ReadDir to prevent infinite
recursion when symlinks create directory cycles.
@fansenze fansenze force-pushed the fix/glob-perf-20260311 branch from 88c6d82 to ab3ecdf Compare March 11, 2026 03:21
@fansenze fansenze merged commit fb86153 into main Mar 11, 2026
14 checks passed
@fansenze fansenze deleted the fix/glob-perf-20260311 branch March 11, 2026 03:38
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants