Page 1 of 1

statScript

Posted: Thu Sep 06, 2007 12:53 am
by s.dot

Code: Select all

<?php

/**
 * Class to generate all kinds of useful information about a script 
 * including the results from stat(), and calculations of system and php
 * memory usage -- before, after, and during script execution.  Times 
 * the script, as well
 *
 * @author - Scott Martin <smp_info _at_ yahoo _dot_ com>
 * @date - September 6th, 2007
 *
 * PHP version 5 >= 5.2 is required.
 */
class statScript
{
	private $_timeStart;
	private $_timeStop;
	private $_memoryUsageBefore;
	private $_memoryUsageAfter;
	private $_memoryPeakUsage;
	private $_phpMemoryUsageBefore;
	private $_phpMemoryUsageAfter;
	private $_phpMemoryPeakUsage;
	private $_script;
	
	public function __construct($script)
	{
		$this->_script = $script;
	}
	
	public function getStats($html = true)
	{
		//we don't want to capture or display output
		ob_start();
		
		//gather memory usage and php memory usage
		$this->_memoryUsageBefore = memory_get_usage(true);
		$this->_phpMemoryUsageBefore = memory_get_usage();
		
		//start timer
		$this->_timeStart = $this->_getTime();
		
		//execute the script
		include $this->_script;
		
		//stop timer
		$this->_timeStop = $this->_getTime();
		
		//gather memory usage and php memory usage
		$this->_memoryUsageAfter = memory_get_usage(true);
		$this->_phpMemoryUsageAfter = memory_get_usage();
		
		//gather peak usage
		$this->_memoryPeakUsage = memory_get_peak_usage(true);
		$this->_phpMemoryPeakUsage = memory_get_peak_usage();
		
		ob_end_clean();
		
		//return output
		if ($html)
		{
			$ret = '<p><strong>Summary</strong> (' . $this->_script . ')</p>
			<p><u>Script Stats</u></p>
			<p>';
			
			$stat = stat($this->_script);
			foreach($stat AS $k => $v)
			{
				if (!is_numeric($k))
				{
					$ret .= '<strong>' . $k . '</strong>: ' . $v . '<br />';
				}
			}
			
			$ret .= '</p>
			
			<p><u>System Memory Stats</u></p>
			<p>Memory usage before script execution: <strong>' . $this->_memoryUsageBefore . '</strong> bytes (' . $this->_getKb($this->_memoryUsageBefore) . ' kb).<br />
			Memory usage after script execution: <strong>' . $this->_memoryUsageAfter . '</strong> bytes (' . $this->_getKb($this->_memoryUsageAfter) . ' kb).<br />
			Peak memory usage during script execution: <strong>' . $this->_memoryPeakUsage . '</strong> bytes (' . $this->_getKb($this->_memoryPeakUsage) . ' kb).<br />
			The script uses between <strong>' . $this->_calculateMemoryDiff() . '</strong> and <strong>' . $this->_calculateMemoryDiffPeak() . '</strong> bytes (' . 
				$this->_getKb($this->_calculateMemoryDiff()) . ' - ' . $this->_getKb($this->_calculateMemoryDiffPeak()) . ' kb) of memory during script execution.</p>
			
			<p><u>PHP Memory Stats</u></p>
			<p>Memory allocated to PHP before script execution: <strong>' . $this->_phpMemoryUsageBefore . '</strong> bytes (' . $this->_getKb($this->_phpMemoryUsageBefore) . ' kb).<br />
			Memory allocated to PHP after script execution: <strong>' . $this->_phpMemoryUsageAfter . '</strong> bytes (' . $this->_getKb($this->_phpMemoryUsageAfter) . ' kb).<br />
			Peak memory allocated to PHP during scipt execution: <strong>' . $this->_phpMemoryPeakUsage . '</strong> bytes (' . $this->_getKb($this->_phpMemoryPeakUsage) . ' kb).<br />
			PHP allocates between <strong>' . $this->_calculatePHPMemoryDiff() . '</strong> and <strong>' . $this->_calculatePHPMemoryDiffPeak() . '</strong> bytes (' . 
				$this->_getKb($this->_calculatePHPMemoryDiff()) . ' - ' . $this->_getKb($this->_calculatePHPMemoryDiffPeak()) . ' kb) of memory during script execution.</p>
			
			<p><u>Execution Time</u></p>
			<p>The script execution time was <strong>' . $this->_calculateExecutionTime() . '</strong> seconds.</p>';
		} else
		{
			$ret = array(
				'MemoryBefore' => $this->_memoryUsageBefore,
				'MemoryBeforeKb' => $this->_getKb($this->_memoryUsageBefore),
				'MemoryAfter' => $this->_memoryUsageAfter,
				'MemoryAfterKb' => $this->_getKb($this->_memoryUsageAfter),
				'MemoryPeakDuring' => $this->_memoryPeakUsage,
				'MemoryPeakDuringKB' => $this->_getKb($this->_memoryPeakUsage),
				'MemoryRangeForScript' => $this->_calculateMemoryDiff() . ' - ' . $this->_calculateMemoryDiffPeak(),
				'MemoryRangeForScriptKb' => $this->_getKb($this->_calculateMemoryDiff()) . ' - ' . $this->_getKb($this->_calculateMemoryDiffPeak()),
				'PHPMemoryBefore' => $this->_phpMemoryUsageBefore,
				'PHPMemoryBeforeKb' => $this->_getKb($this->_phpMemoryUsageBefore),
				'PHPMemoryAfter' => $this->_phpMemoryUsageAfter,
				'PHPMemoryAfterKb' => $this->_getKb($this->_phpMemoryUsageAfter),
				'PHPMemoryPeakDuring' => $this->_phpMemoryPeakUsage,
				'PHPMemoryPeakDuringKB' => $this->_getKb($this->_phpMemoryPeakUsage),
				'PHPMemoryRangeForScript' => $this->_calculatePHPMemoryDiff() . ' - ' . $this->_calculatePHPMemoryDiffPeak(),
				'PHPMemoryRangeForScriptKb' => $this->_getKb($this->_calculatePHPMemoryDiff()) . ' - ' . $this->_getKb($this->_calculatePHPMemoryDiffPeak()),
				'ScriptStats' => stat($this->_script)
			);
			
			$ret = print_r($ret, true);
		}
		
		return $ret;
	}
	
	private function _getTime()
	{
		return microtime(true);
	}
	
	private function _calculateExecutionTime()
	{
		return $this->_timeStop - $this->_timeStart;
	}
	
	private function _calculateMemoryDiff()
	{
		return $this->_memoryUsageAfter - $this->_memoryUsageBefore;
	}
	
	private function _calculateMemoryDiffPeak()
	{
		return $this->_memoryPeakUsage - $this->_memoryUsageBefore;
	}
	
	private function _calculatePHPMemoryDiff()
	{
		return $this->_phpMemoryUsageAfter - $this->_phpMemoryUsageBefore;
	}
	
	private function _calculatePHPMemoryDiffPeak()
	{
		return $this->_phpMemoryPeakUsage - $this->_phpMemoryUsageBefore;
	}
	
	private function _getKb($bytes)
	{
		return $bytes/1024;
	}
}
Usage

Code: Select all

require 'statscript.class.php';
$statScript = new statScript('traffic/includes/php/functions.php');

echo $statScript->getStats();
Output

Code: Select all

Summary (traffic/includes/php/functions.php)

Script Stats

dev: 2
ino: 0
mode: 33206
nlink: 1
uid: 0
gid: 0
rdev: 2
size: 5396
atime: 1179626827
mtime: 1179626827
ctime: 1173083614
blksize: -1
blocks: -1


System Memory Stats

Memory usage before script execution: 262144 bytes (256 kb).
Memory usage after script execution: 262144 bytes (256 kb).
Peak memory usage during script execution: 262144 bytes (256 kb).
The script uses between 0 and 0 bytes (0 - 0 kb) of memory during script execution.

PHP Memory Stats

Memory allocated to PHP before script execution: 137080 bytes (133.8671875 kb).
Memory allocated to PHP after script execution: 174048 bytes (169.96875 kb).
Peak memory allocated to PHP during scipt execution: 207976 bytes (203.1015625 kb).
PHP allocates between 36968 and 70896 bytes (36.1015625 - 69.234375 kb) of memory during script execution.

Execution Time

The script execution time was 0.0019159317016602 seconds.
You can also call getStats(false) which will just return an array of values instead of html markup.

Code: Select all

Array
(
    [MemoryBefore] => 262144
    [MemoryBeforeKb] => 256
    [MemoryAfter] => 262144
    [MemoryAfterKb] => 256
    [MemoryPeakDuring] => 262144
    [MemoryPeakDuringKB] => 256
    [MemoryRangeForScript] => 0 - 0
    [MemoryRangeForScriptKb] => 0 - 0
    [PHPMemoryBefore] => 137400
    [PHPMemoryBeforeKb] => 134.1796875
    [PHPMemoryAfter] => 174360
    [PHPMemoryAfterKb] => 170.2734375
    [PHPMemoryPeakDuring] => 208288
    [PHPMemoryPeakDuringKB] => 203.40625
    [PHPMemoryRangeForScript] => 36960 - 70888
    [PHPMemoryRangeForScriptKb] => 36.09375 - 69.2265625
    [ScriptStats] => Array
        (
            [0] => 2
            [1] => 0
            [2] => 33206
            [3] => 1
            [4] => 0
            [5] => 0
            [6] => 2
            [7] => 5396
            [8] => 1179626827
            [9] => 1179626827
            [10] => 1173083614
            [11] => -1
            [12] => -1
            [dev] => 2
            [ino] => 0
            [mode] => 33206
            [nlink] => 1
            [uid] => 0
            [gid] => 0
            [rdev] => 2
            [size] => 5396
            [atime] => 1179626827
            [mtime] => 1179626827
            [ctime] => 1173083614
            [blksize] => -1
            [blocks] => -1
        )

)
Yes.. boredom once again :P The code could be tidied up a bit. And could add a new method for generating averages.

Posted: Fri Sep 07, 2007 11:05 am
by s.dot
No thoughts eh ;)
Probably another useless one.

Posted: Fri Sep 07, 2007 12:03 pm
by Christopher
Not useless. I think I might separate it into a data gathering class and one or more output classes. Make it so you can write and pass your own output class to it. It could be friendly so that if no outputter is provided it internally instantiates your standard one. Or reverse it and pass the stats objects to the outputter. You could have several outputters -- as system stats one, a PHP stats one, a script states one ...

Posted: Fri Sep 07, 2007 12:31 pm
by TheMoose
I'd also add in a feature to get stats of a code snippet (like $stat->BeginCapture() / EndCapture()) so that I don't necessarily have to put a script into a separate file for inclusion. Say I wanted to go through a heavy procedural script but get stats on how certain portions are working independently of each other, I'd have to put each portion into it's own file to include.

Posted: Sat Sep 08, 2007 10:45 am
by s.dot
Yeah these are all good ideas. I'll probably implement them here in a little bit.

I especcially like the beginCapture() and endCapture() idea.

Posted: Wed Nov 07, 2007 2:34 am
by dbevfat
I would consider including the script within a sandbox (see http://www.php.net/runkit), this can be safer and much more controllable. I don't know if this would affect the results, but it's worth a try.

regards