///PHP Script execution time and maximum workaround

PHP Script execution time and maximum workaround

Ever wondered how long your PHP scripts were taking to execute? Or maybe you’ve broken the maximum execution time limit on your server, as defined in your php.ini’s max_execution_time directive. Well, dealing with PHP script execution time is actually quite easy. In this mini tutorial, I’ll show you how to measure your PHP script execution time, include monitoring at different stages of the process, and work around your max execution time limit.

Measure script execution time

This is the easiest part. PHP’s microtime() function will give you the current timestamp in microseconds (you need that level of precision for script execution time). However, microtime() will give you a value like 0.13554500 978913621, when what you really want is 978913621.13554500 (the 0 taken off the decimal section and added on to the integer). We can take care of this easily with a function we’ll call microtime_float().

So, to implement script execution time, we just take this value at the start of the script and at (or near) the end, then subtract them. First, at the very start of your page’s code, add this function:

function microtime_float()
{
    list($utime, $time) = explode(" ", microtime());
    return ((float)$utime + (float)$time);
}

$script_start = microtime_float();

Then at the end, add this:

$script_end = microtime_float();
echo "Script executed in ".bcsub($script_end, $script_start, 4)." seconds.";

Measure script execution time in stages

We can use milestones in a script to track how certain sections of code are performing. The best way to achieve this is a simple function with some static variable inside. However, needs can quickly get complicated, so I built a simple static class to handle everything. Include this class in your application:

<?php
class ScriptTimer {
  static $milestones;
  function microtime_float() {
    list($utime, $time) = explode(" ", microtime());
    return ((float)$utime + (float)$time);
  }
  function timing_milestone($name) {
    self::$milestones[] = array($name, self::microtime_float());
  }
  function dump_profile($return = false) {
    self::$milestones[] = array('finish', self::microtime_float());
    $output = '<table border="1">'.
              '<tr><th>Milestone</th><th>Diff</th><th>Cumulative</th></tr>';
    foreach (self::$milestones as $elem => $data) {
      $output .= '<tr><td>'.$data[0].'</td>'.
        '<td>'.round(($elem ? $data[1] - self::$milestones[$elem - 1][1]: '0'), 5).'</td>'.
        '<td>'.round(($data[1] - self::$milestones[0][1]), 5).'</td></tr>';
    }
    $output .= '</table>';
    if ($return) return $output;
    echo $output;
  }
}

As you can see, it’s a fairly simple class. It basically stores an array of milestones, each named, in ScriptTimer::$milestones. Each time you call ScriptTimer::timing_milestone(), you pass it a name of the current milestone. This might be ‘begin’, ‘init db’, ‘fetch rss’, ‘end’, or anything you like. When you call ScriptTimeer::dump_profile(), it runs through all these milestones and generates a HTML report. Trying it out in a real application results in something like the following:

Screenshot of PHP Script Timer in action

It’s no full-on profiler, but it can still prove highly useful in quickly performance testing your application. To use it, just call ScriptTimer::timing_milestone(‘some milestone name’) at major sections of your code. This is the testing script I used:

ScriptTimer::timing_milestone('begin');
usleep(3000); // do some db stuff
ScriptTimer::timing_milestone('db ready');
usleep(5200); // do some cache stuff
ScriptTimer::timing_milestone('caches primed');
usleep(8000); // render the output
ScriptTimer::timing_milestone('all output');
usleep(600); // clean up
ScriptTimer::timing_milestone('garbage collected');
ScriptTimer::dump_profile();

I’ve used the usleep() function to simulate loading time – don’t do this in your real application! Just add the ScriptTimer::timing_milestone() calls in, and call ScriptTimer::dump_profile() at the end. No need to initialise; the class works statically for simplicity.

Workaround for max_execution_time limit

Depending on your server configuration, you should be able to work around the max_execution_time script execution time limit very easily. A call to ini_set() should change the value of max_execution_time for the current execution, like so:

ini_set('max_execution_time', '0'); // 0 = no limit.
2008-03-15T08:39:05+00:00 March 15th, 2008|PHP|3 Comments

About the Author:

3 Comments

  1. Lord V8r September 11, 2009 at 11:47 AM

    Thanks!, exactly what I was looking for.

  2. ava February 17, 2010 at 4:56 PM

    Sweet. Thanks so much. This is exactly what I needed.

  3. Clint March 8, 2010 at 1:51 AM

    Very useful! It’s helping me track down which scripts are taking longer than they should.

Leave A Comment