runtime: Guid.NewGuid() is 10x slower on Linux compared to Windows
Guid.NewGuid()
is 10 times slower on Linux compared to Windows.
Slower | diff/base | Windows Median (ns) | Linux Median (ns) | Modality |
---|---|---|---|---|
System.Tests.Perf_Guid.NewGuid | 9.52 | 77.99 | 742.10 |
The contributor who wants to work on this issue should:
- Run this simple benchmark from dotnet/performance repository and confirm the problem
git clone https://github.com/dotnet/performance.git
python3 ./performance/scripts/benchmarks_ci.py -f netcoreapp5.0 --filter System.Tests.Perf_Guid.NewGuid
- Build CoreCLR locally: https://github.com/dotnet/performance/blob/master/docs/profiling-workflow-corefx.md#Build
- Create a small repro app: https://github.com/dotnet/performance/blob/master/docs/profiling-workflow-corefx.md#repro
- Use PerfCollect to identify issue https://github.com/dotnet/performance/blob/master/docs/profiling-workflow-corefx.md#PerfCollect
- Solve the issue
About this issue
- Original URL
- State: open
- Created 5 years ago
- Comments: 30 (30 by maintainers)
I think there is a work here:
getrandom
syscall on Linux (started in #1433, but never finished) orSecRandomCopyBytes
on OSX.@iSazonov You’d continue to use the Framework-provided APIs for generating GUIDs. What I was suggesting is that if you were willing to take the hit of generating a bunch (16? 32?) upfront in a non-perf-critical part of your code, then you could drain that cache in the perf-critical part of your code. There’s no need to roll your own crypto.
That’s not how licensing works. Any derivative of the work is tainted, even if it’s because it influenced the code you later wrote. That’s why many folks adopt a “cooling off” period after seeing such licensed code, in order to avoid accidentally using something they may have remembered from it.
That code also isn’t going to be very relevant. The kernel needs to maintain its own source of cryptographic entropy, something we wouldn’t want to even attempt replicating.
@deeprobin The links you have shared are into GPL licensed projects. GPL license is incompatible with the license of this project. Please refrain from looking at GPL licensed code for areas you would like to contribute for next time.
I still believe that the next thing to do here is to switch from reading urandom to the getrandom syscall (https://github.com/dotnet/runtime/issues/13628#issuecomment-699559874) to reduce the overhead.
Our
Guid.NewGuid()
implementation on Windows delegates toCoCreateGuid
,which as an implementation detail creates GUIDs in batches and caches them. OurGuid.NewGuid()
implementation on non-Windows creates new GUIDs on-demand without caching. That probably explains the perf difference.Edit: Apparently the implementation detail has changed since the last time I looked at it. Both Windows and non-Windows call the PRNG directly every time, at least on latest Win10.
This has been discussed and investigated several times: https://github.com/dotnet/corefx/issues/3573#issuecomment-163703825 https://github.com/dotnet/coreclr/pull/16643#issuecomment-369658313