SystemTools: Optimize FileIsExecutable on Windows
I found this bottleneck on the hottest path, when configuring CMake itself:
(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