Skip to content

Conversation

@reedz
Copy link

@reedz reedz commented Jan 23, 2026

Fixes #13628.
Fixes #107989.

This PR implements two optimizations:

  • getrandom() syscall (if available) instead of reading from /dev/urandom is ~14% quicker >
  • fetching & caching GUIDs in batches in thread local storage for future use via single getrandom() call as performed in Random.Shared

Benchmark dot net benchmark is showing the following changes:

Runtime Mean Improvement
Linux (before) 614.2 ns baseline
Linux (after) 61.16 ns ~10x faster

Copilot AI review requested due to automatic review settings January 23, 2026 11:52
@github-actions github-actions bot added the needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners label Jan 23, 2026
@dotnet-policy-service dotnet-policy-service bot added the community-contribution Indicates that the PR has been added by a community member label Jan 23, 2026
Copy link
Contributor

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 optimizes Guid.NewGuid() on Unix, primarily targeting Linux, by reducing syscall overhead and reusing entropy to significantly improve performance while maintaining cryptographic-strength randomness.

Changes:

  • Teach the native random infrastructure to use getrandom() (when available) instead of /dev/urandom, reducing per-call overhead for cryptographically secure random bytes.
  • Add CMake configuration and header wiring to detect and expose the availability of getrandom.
  • Reimplement Guid.NewGuid() on Unix to use a per-thread cache of GUIDs filled in batches via a single secure-random call, including logic to correctly set RFC 4122 version and variant bits for each cached GUID.

Reviewed changes

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

File Description
src/native/minipal/random.c Adds a HAVE_GETRANDOM-guarded implementation of minipal_get_cryptographically_secure_random_bytes using the getrandom() syscall, looping until the requested buffer is fully populated and handling EINTR, to provide a faster secure RNG backend than /dev/urandom.
src/native/minipal/minipalconfig.h.in Introduces the HAVE_GETRANDOM configuration macro so native code can be conditionally compiled against getrandom() support.
src/native/minipal/configure.cmake Extends the CMake configuration to probe for getrandom in sys/random.h, defining HAVE_GETRANDOM when present so the new native path in random.c is enabled on supported Unix platforms.
src/libraries/System.Private.CoreLib/src/System/Guid.Unix.cs Replaces the per-call secure RNG usage with a [ThreadStatic] cache of 64 GUIDs, filled via a single Interop.GetCryptographicallySecureRandomBytes call and post-processed to set version/variant bits, and updates NewGuid() to draw from this cache (with a WASI-specific non-cached fallback).

@EgorBo
Copy link
Member

EgorBo commented Jan 23, 2026

Managed side cache of secure RNG doesn't sound secure. If NewGuid becomes a bottleneck there are other strategies to make it fast

@stephentoub
Copy link
Member

Related:
#111287
@vcsjones

@reedz
Copy link
Author

reedz commented Jan 24, 2026

@dotnet-policy-service agree

@vcsjones
Copy link
Member

@reedz can you please update your PR's description with performance numbers now that the batching has been removed?

@stephentoub
Copy link
Member

@EgorBot -arm -x64

using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Running;

BenchmarkSwitcher.FromAssembly(typeof(Bench).Assembly).Run(args);

[MemoryDiagnoser]
public class Bench
{
    [Benchmark]
    public Guid New() => Guid.NewGuid();
}

@stephentoub stephentoub enabled auto-merge (squash) January 24, 2026 19:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

community-contribution Indicates that the PR has been added by a community member needs-area-label An area label is needed to ensure this gets routed to the appropriate area owners

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Consider using Linux's getrandom in minipal_get_cryptographically_secure_random_bytes Guid.NewGuid() is 10x slower on Linux compared to Windows

6 participants