minPerformance = $minPerformance; } /** * Run CPU benchmark and return a Success if the result is higher than minimum performance, * Failure if below and a warning if there was a problem with calculating the value of PI. * * @return Failure|Success|Warning */ public function check() { $timeStart = microtime(true); $result = static::calcPi(1000); $duration = microtime(true) - $timeStart; $performance = $duration / $this->baseline; // Check if bcmath extension is present // @codeCoverageIgnoreStart if (!extension_loaded('bcmath')) { return new Warning('Check\CpuPerformance requires BCMath extension to be loaded.'); } // @codeCoverageIgnoreEnd if ($result != $this->expectedResult) { // Ignore code coverage here because it's impractical to test against faulty calculations. // @codeCoverageIgnoreStart return new Warning('PI calculation failed. This might mean CPU or RAM failure', $result); // @codeCoverageIgnoreEnd } elseif ($performance > $this->minPerformance) { return new Success(null, $performance); } else { return new Failure(null, $performance); } } /** * Get decimal expansion of PI using Gauss-Lagendre algorithm. * * @link https://github.com/natmchugh/pi/blob/master/gauss-legendre.php * @link http://en.wikipedia.org/wiki/Calculate_pi#Modern_algorithms * @param $precision * @return string */ public static function calcPi($precision) { $limit = ceil(log($precision) / log(2)) - 1; bcscale($precision + 6); $a = 1; $b = bcdiv(1, bcsqrt(2)); $t = 1 / 4; $p = 1; for ($n = 0; $n < $limit; $n++) { $x = bcdiv(bcadd($a, $b), 2); $y = bcsqrt(bcmul($a, $b)); $t = bcsub($t, bcmul($p, bcpow(bcsub($a, $x), 2))); $a = $x; $b = $y; $p = bcmul(2, $p); } return bcdiv(bcpow(bcadd($a, $b), 2), bcmul(4, $t), $precision); } }