Skip to content

SystemTools: Optimize FileIsExecutable on Windows

I found this bottleneck on the hottest path, when configuring CMake itself: image

(2nd column: samples (8khz profiler), 3rd column: milliseconds)

The problem is that the expensive function GetFileAttributesW (Related cmake/cmake#23154) gets called twice. Once in SystemTools::FileIsDirectory and another time (with the same path) in _waccess. When looking at the implementation of _waccess (located at $YOUR_WINDOWS_SDK_PATH\ucrt\filesystem\waccess.cpp) I found out, that it's just checking if the path exists and that it's not a directory with our passed access mode.

By only calling GetFileAttributesW once and checking if it exists and is not a directory I could improve CMake's performance by quite a bit:

Before:

Benchmark 1: .\out\build\msvc-release\bin\cmake.exe -G Ninja -B build-perf -DCMAKE_BUILD_TYPE=Debug
  Time (mean ± σ):     19.812 s ±  0.127 s    [User: 0.000 s, System: 0.001 s]
  Range (min … max):   19.625 s … 19.985 s    10 runs

After:

Benchmark 1: .\out\build\msvc-release\bin\cmake.exe -G Ninja -B build-perf -DCMAKE_BUILD_TYPE=Debug
  Time (mean ± σ):     19.296 s ±  0.126 s    [User: 0.000 s, System: 0.000 s]
  Range (min … max):   19.129 s … 19.497 s    10 runs

Also I just realized that a way easier approach could have bin, to just remove the call to SystemTools::FileIsDirectory on Windows 🤦 Let me know if you would prefer that implementation...

Edited by Brad King

Merge request reports