Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
This command line PHP script tests algorithm times, keeping track of results in a histogram. Each time a new worst case elapsed time is found, the script will print out metrics, including user cpu time, system cpu time and context switches.
<?php
declare(ticks = 1);
/*
* This command line PHP script tests algorithm times, keeping track of results in a histogram.
* Each time a new worst case elapsed time is found, the script will print out metrics, including
* user cpu time, system cpu time and context switches.
*
* Pressing Cntrl-Z will dump the current stats.
*/
class InteruptTester
{
const MEMORY_SIZE = 1048576; // 1MB
const ITERATION_LIMIT = 7000;
const SLEEP_BETWEEN_TESTS_MS = 100; // Amount of time to sleep between test runs (avoid abusing CPU)
public $worstEvent = null;
public $timeCounts = null;
public $timeBuckets = null;
public $worstTime = 0;
public $eatMemory = null;
protected $usageStart = null;
protected $usageEnd = null;
protected $tStart = 0;
protected $tEnd = 0;
protected $timeSum = 0;
protected $timeAverage = 0;
protected $iterations;
public function __construct()
{
$this->timeBuckets = array(2,6,10,18,24,50,75,100,200,10000);
$this->timeCounts = array(0,0,0,0,0,0,0,0,0,0);
$this->eatMemory = array();
$size = 0;
$chunkSize = 10000;
while ($size < self::MEMORY_SIZE)
{
$this->eatMemory[] = str_pad('pig', $chunkSize, uniqid());
$size += $chunkSize;
}
}
public function main()
{
$uSleep = self::SLEEP_BETWEEN_TESTS_MS * 1000;
while(true)
{
$this->timetest();
usleep($uSleep);
}
}
protected function markStart()
{
$this->usageStart = getrusage();
$this->tStart = microtime(true);
}
protected function markEnd($iterations)
{
$this->tEnd = microtime(true);
$this->usageEnd = getrusage();
$elapsed = round($this->tEnd*1000 - $this->tStart*1000);
$usageDiffKeys = array('ru_nsignals' => 'signals','ru_nivcsw' =>'involSwitch', 'ru_nvcsw' =>'volSwitch',
'ru_minflt' =>'minFault', 'ru_majflt' =>'majFault');
$info = array('elapsed' => $elapsed);
foreach($usageDiffKeys as $key =>$val)
{
$info[$val] = $this->usageEnd[$key] - $this->usageStart[$key];
}
$info['userCPUTime'] = (($this->usageEnd['ru_utime.tv_sec']*1e6+$this->usageEnd['ru_utime.tv_usec']) - ($this->usageStart['ru_utime.tv_sec']*1e6+$this->usageStart['ru_utime.tv_usec']))/1000; // in ms
$info['systemCPUTime'] = (($this->usageEnd['ru_stime.tv_sec']*1e6+$this->usageEnd['ru_stime.tv_usec']) - ($this->usageStart['ru_stime.tv_sec']*1e6+$this->usageStart['ru_stime.tv_usec']))/1000;
$this->countTime($elapsed);
if ($elapsed>$this->worstTime)
{
$this->logEvent($info);
$this->worstEvent = $info;
$this->worstTime = $elapsed;
}
return $info;
}
public function countTime($t)
{
$this->timeSum += $t;
$this->iterations++;
$this->timeAverage = $this->timeSum/$this->iterations;
for($i=0;$i<count($this->timeBuckets);$i++)
{
if ($t<$this->timeBuckets[$i])
{
$this->timeCounts[$i]++;
break;
}
}
}
protected function logEvent($info)
{
print_r($info);
}
public function sigint_handler($signo)
{
$this->showStats();
exit();
}
public function sigstp_handler($signo)
{
$this->showStats();
}
public function showStats()
{
print_r($this->worstEvent);
print("Average time: " . $this->timeAverage . "\n");
$startRange = 0;
for($i=0;$i<count($this->timeBuckets);$i++)
{
print($startRange . '-'. $this->timeBuckets[$i] . ' : ' . $this->timeCounts[$i] . "\n");
$startRange = $this->timeBuckets[$i]+1;
}
}
/*
* This is the algorithm being measured.
*
* Replaces the contents of the loop with your code.
*/
public function timetest()
{
$this->markStart();
$limit = self::ITERATION_LIMIT;
$iterations = 0;
while ($iterations < $limit)
{
$iterations++;
$last=microtime(true);
}
$this->markEnd($iterations);
}
}
$gInteruptTester = new InteruptTester();
pcntl_signal(SIGINT, array($gInteruptTester, 'sigint_handler'));
pcntl_signal(SIGTSTP, array($gInteruptTester, 'sigstp_handler'));
$gInteruptTester->main();
?>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment