function UnixTimeGenerator::increment
Special thanks to Nicolas Grekas for sharing the following information:
Within the same ms, we increment the rand part by a random 24-bit number.
Instead of getting this number from random_bytes(), which is slow, we get it by sha512-hashing self::$seed. This produces 64 bytes of entropy, which we need to split in a list of 24-bit numbers. unpack() first splits them into 16 x 32-bit numbers; we take the first byte of each of these numbers to get 5 extra 24-bit numbers. Then, we consume those numbers one-by-one and run this logic every 21 iterations.
self::$rand holds the random part of the UUID, split into 5 x 16-bit numbers for x86 portability. We increment this random part by the next 24-bit number in the self::$seedParts list and decrement self::$seedIndex.
@link https://twitter.com/nicolasgrekas/status/1583356938825261061 Tweet from Nicolas Grekas
1 call to UnixTimeGenerator::increment()
- UnixTimeGenerator::generate in vendor/
ramsey/ uuid/ src/ Generator/ UnixTimeGenerator.php - @inheritDoc
File
-
vendor/
ramsey/ uuid/ src/ Generator/ UnixTimeGenerator.php, line 128
Class
- UnixTimeGenerator
- UnixTimeGenerator generates bytes that combine a 48-bit timestamp in milliseconds since the Unix Epoch with 80 random bits
Namespace
Ramsey\Uuid\GeneratorCode
private function increment() : string {
if (self::$seedIndex === 0 && self::$seed !== null) {
self::$seed = hash('sha512', self::$seed, true);
/** @var int[] $s */
$s = unpack('l*', self::$seed);
$s[] = $s[1] >> 8 & 0xff0000 | $s[2] >> 16 & 0xff00 | $s[3] >> 24 & 0xff;
$s[] = $s[4] >> 8 & 0xff0000 | $s[5] >> 16 & 0xff00 | $s[6] >> 24 & 0xff;
$s[] = $s[7] >> 8 & 0xff0000 | $s[8] >> 16 & 0xff00 | $s[9] >> 24 & 0xff;
$s[] = $s[10] >> 8 & 0xff0000 | $s[11] >> 16 & 0xff00 | $s[12] >> 24 & 0xff;
$s[] = $s[13] >> 8 & 0xff0000 | $s[14] >> 16 & 0xff00 | $s[15] >> 24 & 0xff;
self::$seedParts = $s;
self::$seedIndex = 21;
}
self::$rand[5] = 0xffff & ($carry = self::$rand[5] + 1 + (self::$seedParts[self::$seedIndex--] & 0xffffff));
self::$rand[4] = 0xffff & ($carry = self::$rand[4] + ($carry >> 16));
self::$rand[3] = 0xffff & ($carry = self::$rand[3] + ($carry >> 16));
self::$rand[2] = 0xffff & ($carry = self::$rand[2] + ($carry >> 16));
self::$rand[1] += $carry >> 16;
if (0xfc00 & self::$rand[1]) {
$time = self::$time;
$mtime = (int) substr($time, -9);
if ($this->intSize >= 8 || strlen($time) < 10) {
$time = (string) ((int) $time + 1);
}
elseif ($mtime === 999999999) {
$time = 1 + (int) substr($time, 0, -9) . '000000000';
}
else {
$mtime++;
$time = substr_replace($time, str_pad((string) $mtime, 9, '0', STR_PAD_LEFT), -9);
}
$this->randomize($time);
}
return self::$time;
}