csharpier icon indicating copy to clipboard operation
csharpier copied to clipboard

perf: use `FileSystemEnumerator`

Open TimothyMakkison opened this issue 1 month ago • 0 comments

Use FileSystemEnumerator to replace Directory.EnumerateFiles, this will only match valid CSharpier file types and skips large always ignored directories, like /bin or /.git

Note that this doesn't use IFileSystem.Directory.EnumerateFiles I've checked the implementation of DirectoryWrapper -> FileSystemEnumerableFactory.UserEntries which internally uses FileSystemEnumerable, so this is functionally the same but skips invalid files and ignored directories.

Unfortunately this causes an issue for the CLI.Tests as it uses MockFileSystem which doesn't really call FileSystemEnumerable causing the tests to fail. I added a fallback check for MockFileSystem but it feels extremely hacky and potentially error prone.

  • Did wonder if it's worth implementing IEnumerable in ValidFilesEnumerator.
  • It might be worth parsing gitignore and csharpierignore while parsing, it would slow things down due to reading files synchronously but it would avoid searching a lot of directories.
    • This would require a rework of how ValidFilesEnumerator searches folders as we'd first have to check for ignore files before we can start yielding files as they may have been ignored.

Benchmarks

This change will have a varying impact on different projects. For instance my csharpier project has 20,000 files in it, most of which are probably in bin, git and benchmarks results. This will reduce the impact of #1743 and #1740

Before

Method Mean Error StdDev Gen0 Gen1 Allocated
FormatCli 949.7 ms 18.81 ms 35.32 ms 9000.0000 1000.0000 81.49 MB

After

Method Mean Error StdDev Gen0 Allocated
FormatCli 653.9 ms 13.03 ms 31.97 ms 4000.0000 35.17 MB

TimothyMakkison avatar Nov 14 '25 14:11 TimothyMakkison