3v4l.org

run code in 300+ PHP versions simultaneously
<? /** * Blame Scott Arciszewski of Paragon Initiative Enterprises for this atrocity. * * https://paragonie.com */ class DeterministicRandom { protected $counter; public function __construct(string $seed = '', int $counter = 0) { $this->seed('set', $seed); $this->counter = 0; } private function seed(string $action = 'get', string $data = '') { static $seed = null; if ($action === 'set') { $seed = $data; } elseif ($action === 'get') { return $data; } else { throw new \Error( 'Unknown action' ); } } public function getBytes(int $numBytes): string { return \openssl_encrypt( \str_repeat("\0", $numBytes), 'aes-128-ctr', $this->seed('get'), OPENSSL_RAW_DATA, $this->getNonce($numBytes) ); } public function getInt(int $min, int $max): int { /** * Now that we've verified our weak typing system has given us an integer, * let's validate the logic then we can move forward with generating random * integers along a given range. */ if ($min > $max) { throw new Error( 'Minimum value must be less than or equal to the maximum value' ); } if ($max === $min) { return $min; } /** * Initialize variables to 0 * * We want to store: * $bytes => the number of random bytes we need * $mask => an integer bitmask (for use with the &) operator * so we can minimize the number of discards */ $attempts = $bits = $bytes = $mask = $valueShift = 0; /** * At this point, $range is a positive number greater than 0. It might * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to * a float and we will lose some precision. */ $range = $max - $min; /** * Test for integer overflow: */ if (!is_int($range)) { /** * Still safely calculate wider ranges. * Provided by @CodesInChaos, @oittaa * * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 * * We use ~0 as a mask in this case because it generates all 1s * * @ref https://eval.in/400356 (32-bit) * @ref http://3v4l.org/XX9r5 (64-bit) */ $bytes = PHP_INT_SIZE; $mask = ~0; } else { /** * $bits is effectively ceil(log($range, 2)) without dealing with * type juggling */ while ($range > 0) { if ($bits % 8 === 0) { ++$bytes; } ++$bits; $range >>= 1; $mask = $mask << 1 | 1; } $valueShift = $min; } /** * Now that we have our parameters set up, let's begin generating * random integers until one falls between $min and $max */ do { /** * The rejection probability is at most 0.5, so this corresponds * to a failure probability of 2^-128 for a working RNG */ if ($attempts > 128) { throw new Exception( 'random_int: RNG is broken - too many rejections' ); } /** * Let's grab the necessary number of random bytes */ $randomByteString = $this->getBytes($bytes); if ($randomByteString === false) { throw new Exception( 'Random number generator failure' ); } /** * Let's turn $randomByteString into an integer * * This uses bitwise operators (<< and |) to build an integer * out of the values extracted from ord() * * Example: [9F] | [6D] | [32] | [0C] => * 159 + 27904 + 3276800 + 201326592 => * 204631455 */ $val = 0; for ($i = 0; $i < $bytes; ++$i) { $val |= ord($randomByteString[$i]) << ($i * 8); } /** * Apply mask */ $val &= $mask; $val += $valueShift; ++$attempts; /** * If $val overflows to a floating point number, * ... or is larger than $max, * ... or smaller than $min, * then try again. */ } while (!is_int($val) || $val > $max || $val < $min); return (int) $val; } protected function getNonce(int $increment = 0): string { $nonce = ''; $ctr = $this->counter; while ($ctr > 0) { $nonce = \chr($ctr & 0xFF) . $nonce; $ctr >>= 8; } $this->counter += $increment; return \str_pad($nonce, 16, "\0", STR_PAD_LEFT); } } $seed = str_repeat("\x80", 16); $rnd1 = new DeterministicRandom($seed); $rnd2 = new DeterministicRandom($seed); $out1 = $rnd1->getBytes(16); $out2 = $rnd1->getBytes(16); $out3 = $rnd2->getBytes(32); $int1 = $rnd1->getInt(0, 255); $int2 = $rnd2->getInt(0, 255); var_dump([ bin2hex($out1), bin2hex($out2), bin2hex($out3), $int1, $int2 ]);

Here you find the average performance (time & memory) of each version. A grayed out version indicates it didn't complete successfully (based on exit-code).

VersionSystem time (s)User time (s)Memory (MiB)
8.3.60.0040.01116.50
8.3.50.0140.00716.35
8.3.40.0120.00818.75
8.3.30.0120.00318.59
8.3.20.0000.00820.34
8.3.10.0080.00021.85
8.3.00.0080.00023.32
8.2.180.0100.01018.16
8.2.170.0070.01022.96
8.2.160.0030.01020.35
8.2.150.0040.00424.18
8.2.140.0040.00424.66
8.2.130.0080.00019.66
8.2.120.0040.00426.35
8.2.110.0030.00621.18
8.2.100.0040.00718.03
8.2.90.0040.00419.27
8.2.80.0000.00917.97
8.2.70.0030.00617.50
8.2.60.0000.00817.91
8.2.50.0000.00818.07
8.2.40.0040.00422.27
8.2.30.0040.00419.23
8.2.20.0040.00417.49
8.2.10.0050.00317.89
8.2.00.0070.00017.92
8.1.280.0140.00025.92
8.1.270.0030.00623.91
8.1.260.0080.00028.09
8.1.250.0040.00428.09
8.1.240.0060.00323.98
8.1.230.0080.00419.16
8.1.220.0040.00417.74
8.1.210.0000.00818.77
8.1.200.0040.00417.23
8.1.190.0040.00417.11
8.1.180.0030.00618.10
8.1.170.0040.00418.46
8.1.160.0050.00220.64
8.1.150.0040.00418.77
8.1.140.0000.00819.41
8.1.130.0030.00317.45
8.1.120.0070.00017.23
8.1.110.0040.00417.32
8.1.100.0030.00517.27
8.1.90.0040.00417.21
8.1.80.0000.00717.30
8.1.70.0040.00417.33
8.1.60.0050.00317.36
8.1.50.0060.00317.42
8.1.40.0020.00517.31
8.1.30.0000.00817.49
8.1.20.0030.00617.51
8.1.10.0040.00417.45
8.1.00.0000.00917.45
8.0.300.0050.00318.77
8.0.290.0050.00216.75
8.0.280.0000.00718.38
8.0.270.0030.00317.27
8.0.260.0000.00617.20
8.0.250.0030.00316.83
8.0.240.0040.00416.77
8.0.230.0030.00316.74
8.0.220.0040.00416.76
8.0.210.0040.00416.72
8.0.200.0000.00716.72
8.0.190.0050.00316.71
8.0.180.0070.00016.70
8.0.170.0050.00316.70
8.0.160.0000.00716.76
8.0.150.0040.00416.79
8.0.140.0030.00616.61
8.0.130.0000.00613.41
8.0.120.0000.00816.69
8.0.110.0000.00816.66
8.0.100.0070.00016.64
8.0.90.0050.00316.55
8.0.80.0090.00616.69
8.0.70.0040.00416.66
8.0.60.0070.00016.79
8.0.50.0050.00316.79
8.0.30.0080.01117.04
8.0.20.0100.00817.40
8.0.10.0040.00416.77
8.0.00.0100.01216.87
7.4.330.0000.00516.79
7.4.320.0030.00316.29
7.4.300.0000.01016.52
7.4.290.0030.00316.40
7.4.280.0000.00916.41
7.4.270.0000.00816.39
7.4.260.0000.00716.40
7.4.250.0040.00416.38
7.4.240.0030.00316.50
7.4.230.0050.00216.58
7.4.220.0150.00916.40
7.4.210.0120.00716.51
7.4.200.0000.00716.51
7.4.160.0090.00616.32
7.4.150.0160.00817.40
7.4.140.0110.00917.86
7.4.130.0110.00716.32
7.4.120.0070.01016.51
7.4.110.0080.00816.32
7.4.100.0090.00916.29
7.4.90.0120.00916.55
7.4.80.0120.00619.39
7.4.70.0030.01316.55
7.4.60.0080.00816.52
7.4.50.0110.00816.39
7.4.40.0030.01316.50
7.4.30.0090.01316.56
7.4.00.0070.01014.82
7.3.330.0050.00013.50
7.3.320.0000.00513.46
7.3.310.0030.00315.93
7.3.300.0070.00016.13
7.3.290.0030.00316.19
7.3.280.0120.00716.13
7.3.270.0130.00417.40
7.3.260.0170.00016.24
7.3.250.0120.00716.42
7.3.240.0070.01016.48
7.3.230.0110.00616.39
7.3.210.0130.00916.35
7.3.200.0140.01419.39
7.3.190.0130.00616.13
7.3.180.0100.00616.19
7.3.170.0090.01216.27
7.3.160.0130.01016.22
7.3.120.0030.01414.55
7.3.110.0090.00614.84
7.3.100.0080.00814.75
7.3.90.0000.01914.86
7.3.80.0060.00614.39
7.3.70.0050.00614.65
7.3.60.0060.00314.63
7.3.50.0070.00314.64
7.3.40.0030.00914.83
7.3.30.0000.01214.66
7.3.20.0110.00416.65
7.3.10.0120.00316.45
7.3.00.0060.00616.58
7.2.330.0030.01416.50
7.2.320.0130.00916.63
7.2.310.0000.01716.39
7.2.300.0100.00716.25
7.2.290.0060.01616.68
7.2.250.0030.01614.84
7.2.240.0070.01414.94
7.2.230.0120.00315.00
7.2.220.0060.00914.72
7.2.210.0060.00615.00
7.2.200.0090.00614.98
7.2.190.0130.00014.86
7.2.180.0110.00314.77
7.2.170.0000.00914.46
7.2.60.0100.00716.81
7.2.00.0090.00319.67
7.1.330.0090.00915.44
7.1.320.0040.01215.43
7.1.310.0070.01015.66
7.1.300.0030.00615.69
7.1.290.0030.00815.27
7.1.280.0040.01115.66
7.1.270.0000.01115.62
7.1.260.0080.00015.38
7.1.200.0040.00715.59
7.1.100.0070.00718.06
7.1.70.0050.00217.08
7.1.60.0040.01419.30
7.1.50.0120.00917.09
7.1.00.0030.07722.66
7.0.200.0000.00816.46
7.0.60.0200.08021.75
7.0.50.0000.07018.02
7.0.40.0030.05720.12
7.0.30.0230.07020.51
7.0.20.0330.07020.21
7.0.10.0070.08320.18
7.0.00.0030.09720.18
5.6.280.0030.05720.79
5.6.210.0100.04320.48
5.6.200.0070.04318.24
5.6.190.0130.07720.41
5.6.180.0270.04320.55
5.6.170.0170.05020.55
5.6.160.0070.04020.45
5.6.150.0100.07718.17
5.6.140.0100.07718.21
5.6.130.0000.04318.14
5.6.120.0030.09021.13
5.6.110.0070.08021.02
5.6.100.0030.08320.93
5.6.90.0170.03720.95
5.6.80.0130.07020.51
5.5.350.0330.07720.41
5.5.340.0000.08317.99
5.5.330.0100.07020.32
5.5.320.0670.06720.36
5.5.310.0170.04320.26
5.5.300.0100.06718.03
5.5.290.0170.07718.05
5.5.280.0070.05020.77
5.5.270.0100.06720.73
5.5.260.0100.04020.76
5.5.250.0030.05020.79
5.5.240.0170.07720.27

preferences:
60.55 ms | 400 KiB | 5 Q