Skip to content

perf: respect ignore rules in Swift module discovery#2

Merged
WendellXY merged 2 commits into
mainfrom
perf/swift-module-discovery-ignore-rules
May 27, 2026
Merged

perf: respect ignore rules in Swift module discovery#2
WendellXY merged 2 commits into
mainfrom
perf/swift-module-discovery-ignore-rules

Conversation

@WendellXY
Copy link
Copy Markdown
Collaborator

Summary

Indexing a Rust project (this repo) froze for ~13–21s with no phase in the progress output accounting for the time. Root cause: grapha-swift's discover_swift_packages_recursive hand-rolled a recursive directory walk that skipped only hidden dirs and node_modules/build/DerivedData/Pods — it did not skip Cargo's target/ nor honor .gitignore. Swift module discovery runs even for pure-Rust projects (the Swift plugin is always registered), so it stat/read_dir'd through the entire build-artifact tree (here: ~60 GB, 15,419 directories).

It hid from the timings because it runs inside discover_modules, in the untimed gap between the "discovered files" and "extracting" phase prints — so per-phase numbers summed to ~0.6s while wall time was 13–21s. A profiler sample confirmed ~92% of runtime was in discover_swift_packages_recursivestat/getdirentries inside target/.

Fix

Replace the hand-rolled walk with ignore::WalkBuilder — the same ignore-aware walker grapha/src/discover.rs already uses for source-file discovery, so the two are now consistent. It:

  • honors .gitignore (require_git(false) so it also applies to non-git checkouts),
  • skips hidden dirs,
  • explicitly prunes build trees (node_modules/build/DerivedData/Pods/target) as belt-and-suspenders,
  • preserves the original semantics: Sources/Tests target registration, and a package nested inside another package is registered once (lexical-sort ancestor dedup).

Result

Indexing this project drops from ~13–21s to 0.6s.

Test plan

  • cargo test -p grapha-swift — 116 tests pass, incl. 3 new regression tests:
    • prunes_build_artifact_directories (Package.swift under target/ is ignored)
    • skips_gitignored_directories
    • nested_package_is_registered_once
  • cargo clippy -p grapha-swift --all-targets — clean
  • End-to-end: grapha index . on this repo verified 0.6s with identical node/edge counts

🤖 Generated with Claude Code

discover_swift_packages_recursive hand-rolled a recursive directory walk
that skipped only hidden dirs and node_modules/build/DerivedData/Pods. It
did not skip Cargo's target/ nor honor .gitignore, so indexing a Rust
project stat'd its way through the entire build-artifact tree (60G,
15k+ dirs here). Because module discovery runs in an untimed gap between
the "discovered" and "extracting" phase prints, this showed up as a
multi-second freeze that the per-phase timings did not explain.

Replace the hand-rolled walk with ignore::WalkBuilder — the same
ignore-aware walker discover.rs already uses for source files — honoring
.gitignore (require_git(false) so it also applies in non-git checkouts),
skipping hidden dirs, and explicitly pruning build trees including
target/. Package registration semantics are preserved (Sources/Tests
registration; a package nested inside another is registered once via
lexical-sort ancestor dedup).

Indexing this project drops from ~13-21s to 0.6s.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings May 27, 2026 05:52
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR improves Swift module discovery performance by replacing a custom recursive filesystem walk with an ignore-aware walker, preventing Swift discovery from scanning large ignored/build artifact trees in non-Swift projects.

Changes:

  • Uses ignore::WalkBuilder to honor .gitignore, hidden directories, and explicit build-directory pruning.
  • Refactors Swift package and test target registration into helper functions.
  • Adds regression tests for ignored directories, build artifact pruning, and nested package handling.

Reviewed changes

Copilot reviewed 2 out of 3 changed files in this pull request and generated 1 comment.

File Description
grapha-swift/src/module_discovery.rs Reworks Swift package discovery and adds regression tests.
grapha-swift/Cargo.toml Adds the ignore dependency.
Cargo.lock Records ignore as a grapha-swift dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +31 to +35
.filter_entry(|entry| {
!entry
.file_name()
.to_str()
.is_some_and(|name| PRUNED_DIRS.contains(&name))
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@WendellXY WendellXY merged commit e931bd6 into main May 27, 2026
4 checks passed
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.

3 participants