statScript

Coding Critique is the place to post source code for peer review by other members of DevNetwork. Any kind of code can be posted. Code posted does not have to be limited to PHP. All members are invited to contribute constructive criticism with the goal of improving the code. Posted code should include some background information about it and what areas you specifically would like help with.

Popular code excerpts may be moved to "Code Snippets" by the moderators.

Moderator: General Moderators

Post Reply
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

statScript

Post 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.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post by s.dot »

No thoughts eh ;)
Probably another useless one.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
Christopher
Site Administrator
Posts: 13596
Joined: Wed Aug 25, 2004 7:54 pm
Location: New York, NY, US

Post 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 ...
(#10850)
User avatar
TheMoose
Forum Contributor
Posts: 351
Joined: Tue May 23, 2006 10:42 am

Post 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.
User avatar
s.dot
Tranquility In Moderation
Posts: 5001
Joined: Sun Feb 06, 2005 7:18 pm
Location: Indiana

Post 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.
Set Search Time - A google chrome extension. When you search only results from the past year (or set time period) are displayed. Helps tremendously when using new technologies to avoid outdated results.
User avatar
dbevfat
Forum Contributor
Posts: 126
Joined: Tue Jun 28, 2005 2:47 pm
Location: Ljubljana, Slovenia

Post 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
Post Reply