Skip to content

Commit

Permalink
Un-inline fallback code in unpredictableSeed (#76)
Browse files Browse the repository at this point in the history
* Un-inline fallback code in unpredictableSeed

`unpredictableSeed` includes a block of fallback code which is seldom
called. Moving this to a separate function and preventing it from being
inlined will improve cache-friendliness.

* Use _expect in unpredictableSeed to hint the fallback is probably not called
  • Loading branch information
n8sh authored and 9il committed Mar 9, 2018
1 parent b0a4313 commit 23c6e8a
Showing 1 changed file with 53 additions and 45 deletions.
98 changes: 53 additions & 45 deletions source/mir/random/engine/package.d
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,7 @@ pragma(inline, true)
@property T unpredictableSeedOf(T)() @trusted nothrow @nogc
if (isUnsigned!T)
{
import mir.ndslice.internal: _expect;
T seed = void;
version (GOOD_ARC4RANDOM_BUF)
{
Expand All @@ -250,56 +251,63 @@ pragma(inline, true)
else
arc4random_buf(&seed, seed.sizeof);
}
else if (_expect(genRandomNonBlocking(&seed, seed.sizeof) != T.sizeof, false))
{
// fallback to old time/thread-based implementation in case of errors
seed = cast(T) fallbackSeed();
}
return seed;
}

pragma(inline, false)
private ulong fallbackSeed()()
{
// fallback to old time/thread-based implementation in case of errors
else if (genRandomNonBlocking(&seed, seed.sizeof) != T.sizeof)
version(Windows)
{
version(Windows)
{
import core.sys.windows.winbase : QueryPerformanceCounter;
ulong ticks = void;
QueryPerformanceCounter(cast(long*)&ticks);
}
else
version(Darwin)
{
import core.time : mach_absolute_time;
ulong ticks = mach_absolute_time();
}
else
version(Posix)
{
import core.sys.posix.time : clock_gettime, CLOCK_MONOTONIC, timespec;
timespec ts;
if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
{
import core.internal.abort : abort;
abort("Call to clock_gettime failed.");
}
ulong ticks = (cast(ulong) ts.tv_sec << 32) ^ ts.tv_nsec;
}
version(Posix)
{
import core.sys.posix.unistd : getpid;
import core.sys.posix.pthread : pthread_self;
auto pid = cast(uint) getpid;
auto tid = cast(uint) pthread_self();
}
else
version(Windows)
import core.sys.windows.winbase : QueryPerformanceCounter;
ulong ticks = void;
QueryPerformanceCounter(cast(long*)&ticks);
}
else
version(Darwin)
{
import core.time : mach_absolute_time;
ulong ticks = mach_absolute_time();
}
else
version(Posix)
{
import core.sys.posix.time : clock_gettime, CLOCK_MONOTONIC, timespec;
timespec ts;
if(clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
{
import core.sys.windows.winbase : GetCurrentProcessId, GetCurrentThreadId;
auto pid = cast(uint) GetCurrentProcessId;
auto tid = cast(uint) GetCurrentThreadId;
import core.internal.abort : abort;
abort("Call to clock_gettime failed.");
}
ulong k = ((cast(ulong)pid << 32) ^ tid) + ticks;
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
seed = cast(T)k;
ulong ticks = (cast(ulong) ts.tv_sec << 32) ^ ts.tv_nsec;
}
return seed;
version(Posix)
{
import core.sys.posix.unistd : getpid;
import core.sys.posix.pthread : pthread_self;
auto pid = cast(uint) getpid;
auto tid = cast(uint) pthread_self();
}
else
version(Windows)
{
import core.sys.windows.winbase : GetCurrentProcessId, GetCurrentThreadId;
auto pid = cast(uint) GetCurrentProcessId;
auto tid = cast(uint) GetCurrentThreadId;
}
ulong k = ((cast(ulong)pid << 32) ^ tid) + ticks;
k ^= k >> 33;
k *= 0xff51afd7ed558ccd;
k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33;
return k;
}

///
Expand Down

0 comments on commit 23c6e8a

Please sign in to comment.