cmSystemTools: Add RandomNumber method that avoid re-seeding from OS

When profiling Qt builds on macos, about 2.2% of a `cmake` invocation
was spent reading from `/dev/urandom`.  Use a (thread)local rng to
mitigate this cost, particularly in `cmGeneratedFileStreamBase::Open`.
This commit is contained in:
Tim Blechmann 2024-12-27 12:07:04 +08:00 committed by Brad King
parent 5da296b805
commit 339c2b886a
6 changed files with 31 additions and 5 deletions

View File

@ -723,7 +723,7 @@ void cmCTestMultiProcessHandler::StartNextTestsOnTimer()
// Wait between 1 and 5 seconds before trying again.
unsigned int const milliseconds = this->FakeLoadForTesting
? 10
: (cmSystemTools::RandomSeed() % 5 + 1) * 1000;
: (cmSystemTools::RandomNumber() % 5 + 1) * 1000;
this->StartNextTestsOnTimer_.start(
[](uv_timer_t* timer) {
uv_timer_stop(timer);

View File

@ -359,7 +359,7 @@ cm::optional<cmTryCompileResult> cmCoreTryCompile::TryCompileCode(
of the same executable name (some filesystems fail on that). */
char targetNameBuf[64];
snprintf(targetNameBuf, sizeof(targetNameBuf), "cmTC_%05x",
cmSystemTools::RandomSeed() & 0xFFFFF);
cmSystemTools::RandomNumber() & 0xFFFFF);
targetName = targetNameBuf;
}

View File

@ -139,7 +139,7 @@ void cmGeneratedFileStreamBase::Open(std::string const& name)
} else {
char buf[64];
snprintf(buf, sizeof(buf), "tmp%05x",
cmSystemTools::RandomSeed() & 0xFFFFF);
cmSystemTools::RandomNumber() & 0xFFFFF);
this->TempName += buf;
}

View File

@ -18,6 +18,14 @@
# define _DARWIN_C_SOURCE
#endif
#ifndef __has_feature
# define __has_feature(x) 0
#endif
#if !defined(__clang__) || __has_feature(cxx_thread_local)
# define CM_HAVE_THREAD_LOCAL
#endif
#include "cmSystemTools.h"
#include <iterator>
@ -79,10 +87,15 @@
#include <functional>
#include <iostream>
#include <memory>
#include <random>
#include <sstream>
#include <utility>
#include <vector>
#ifndef CM_HAVE_THREAD_LOCAL
# include <mutex>
#endif
#include <fcntl.h>
#include "cmsys/Directory.hxx"
@ -2810,6 +2823,18 @@ unsigned int cmSystemTools::RandomSeed()
#endif
}
unsigned int cmSystemTools::RandomNumber()
{
#ifndef CM_HAVE_THREAD_LOCAL
static std::mutex gen_mutex;
std::lock_guard<std::mutex> gen_mutex_lock(gen_mutex);
#else
thread_local
#endif
static std::mt19937 gen{ cmSystemTools::RandomSeed() };
return static_cast<unsigned int>(gen());
}
namespace {
std::string InitLogicalWorkingDirectory()
{

View File

@ -540,8 +540,9 @@ public:
static void EnsureStdPipes();
/** Random seed generation. */
/** Random number generation. */
static unsigned int RandomSeed();
static unsigned int RandomNumber();
/** Find the directory containing CMake executables. */
static void FindCMakeResources(const char* argv0);

View File

@ -211,7 +211,7 @@ bool cmakeCheckStampFile(const std::string& stampName)
// The build system is up to date. The stamp file has been removed
// by the VS IDE due to a "rebuild" request. Restore it atomically.
std::ostringstream stampTempStream;
stampTempStream << stampName << ".tmp" << cmSystemTools::RandomSeed();
stampTempStream << stampName << ".tmp" << cmSystemTools::RandomNumber();
std::string stampTemp = stampTempStream.str();
{
// TODO: Teach cmGeneratedFileStream to use a random temp file (with