PHP Benchmarking Redux

May 18

So after the comment from Jay in regards to my previous post about PHP benchmarking I decided to sit down and write a PHP class for my upcoming framework that handles benchmarking.

Usage is is fairly simple and is as follows:

$benchmark = \IMorf\Benchmark::getInstance();
$benchmark->startTimer('fullLoad');
$benchmark->startMemoryTracker('fullLoad');
/**
 * Lots and Lots of code here
 */
$benchmark->startTime('someOtherTime');
/**
 * More code
 * and at the end or wherever you want to echo
 */
echo $benchmark->getTimer('someOtherTime');
echo $benchmark->getTimer('fullLoad');
echo $benchmark->getMemoryTracker('fullLoad');

Its a fairly simple class but provides for tracking different elements of your application on the fly. Here’s the code I will be using. If you have any questions let me know.

<?php
/**
 * iMorf PHP Framework - Morphing PHP one line at a time
 *
 * LICENSE
 *
 * This source file is subject to the new BSD license that is bundled with
 * this package in the file LICENSE.txt. It is also available through the
 * world-wide-web at this URL:
 * {@link http://www.imorf.com/license/new-bsd}
 * If you did not receive a copy of the license and are unable to obtain
 * it through our website, please send an email to license@imorf.com
 * so we can send you a copy immediately.
 *
 * @category   iMorf
 * @package    Benchmark
 * @copyright  Copyright (c) 2010 Xistins Technologies {@link http://www.xistins.com}
 * @author     Christian South [csouth (at) xistins (dot) com] {@link http://www.christiansouth.com}
 * @version    v0.0.1d
 */
namespace IMorf;

/**
 * Base Benchmark
 * Inspiration from Jay Gilford {@link http://www.jaygilford.com/php/simple-timer-class-for-benchmarking/}
 *
 * @category   iMorf
 * @package    Benchmark
 * @copyright  Copyright (c) 2010 Xistins Technologies {@link http://www.xistins.com}
 * @author     Christian South [csouth (at) xistins (dot) com] {@link http://www.christiansouth.com}
 * @version    v0.0.1d
 */
class Benchmark
{
    /**
     * Singleton Instance
     * @var iMorf\Benchmark
     */
    protected static $_instance = null;

    /**
     * All application timers
     * @var array
     */
    protected $_timers = array();

    /**
     * All application memory trackers
     * @var array
     */
    protected $_memoryTrackers = array();

    /**
     * All times left
     * @var array
     */
    protected $_times = array();

    /**
     * All application memory trackers
     * @var array
     */
    protected $_memory = array();

    /**
     * Return all memory trackers
     *
     * @return array
     */
    public function getAllMemoryTrackers()
    {
        foreach($this->_memoryTrackers as $memoryName => $memory) {
            $this->stopMemoryTracker($memoryName);
        }

        return $this->_memory;
    }

    /**
     * Return all times
     *
     * @return array
     */
    public function getAllTimes()
    {
        foreach($this->_timers as $timerName => $time) {
            $this->stopTimer($timerName);
        }

        return $this->_times;
    }

    /**
     * Singleton Instance
     *
     * @return iMorf\Benchmark
     */
    public static function getInstance()
    {
        if(null === self::$_instance) {
            self::$_instance = new self;
        }

        return self::$_instance;
    }

    /**
     * Get Memory Tracker
     *
     * @param  string $name Unique memory tacker name
     * @return float
     */
    public function getMemoryTracker($name, $decimals = 2)
    {
        if(isset($this->_memoryTrackers[$name])) {
            $this->stopMemoryTracker($name);
        }

        if(!isset($this->_memory[$name])) {
            throw new Exception("Unable to get memory tracker by the name of $name");
        }

        return number_format(($this->_memory[$name]/1000), $decimals);
    }

    /**
     * Get a time
     *
     * @param  string $name Unique timer name
     * @return float
     */
    public function getTimer($name, $decimals = 3)
    {
        /**
         * Stop Timer if its started
         */
        if(isset($this->_timers[$name])) {
            $this->stopTimer($name);
        }

        if(!isset($this->_times[$name])) {
            throw new Exception("Unable to get time for timer by the name of $name");
        }

        return number_format($this->_times[$name], $decimals);
    }

    /**
     * Start Memory Tracker
     *
     * @param  string $name Unique memory tracker name
     * @return iMorf\Benchmark
     */
    public function startMemoryTracker($name)
    {
        if(isset($this->_memoryTrackers[$name]) || isset($this->_memory[$name])) {
            throw new Exception("A memory tracker by the name of $name already exists");
        }

        $this->_memoryTrackers[$name] = memory_get_usage();
        return $this;
    }

    /**
     * Start Timer
     *
     * @param  string $name Unique timer name
     * @return iMorf\Benchmark
     */
    public function startTimer($name)
    {
        if(isset($this->_timers[$name]) || isset($this->_times[$name])) {
            throw new Exception("A timer by the name of $name already exists");
        }

        $this->_timers[$name] = microtime(true);
        return $this;
    }

    /**
     * Stop Memory Tracker
     *
     * @param  string $name Unique memory tracker name
     * @return iMorf\Benchmark
     */
    public function stopMemoryTracker($name)
    {
        if(!isset($this->_memoryTrackers[$name])) {
            throw new Exception("You don't have a memory tracker by the name of $name");
        }

        $memory = memory_get_usage();
        unset($this->_memoryTrackers[$name]);

        $this->_memory[$name] = $memory - memory_get_usage();
        return $this;
    }

    /**
     * Stop Timer
     *
     * @param  string $name Unique timer name
     * @return iMorf\Benchmark
     */
    public function stopTimer($name)
    {
        if(!isset($this->_timers[$name])) {
            throw new Exception("You don't have a timer by the name of $name");
        }

        $time = $this->_timers[$name];
        unset($this->_timers[$name]);

        $this->_times[$name] = microtime(true) - $time;
        return $this;
    }
}

Leave a Reply