Format microtime() to provide better feedback on the time elapsed

As a PHP developer you know that it’s common task to check how long a particular class, function or procedure performs. Usually this involves measuring of the time particular code snippet takes to execute. There are lots of PHP code benchmark scripts out there, but the simplest method remains to check the difference between the start and end time.

// Get the current Unix timestamp with microseconds as float, so we can do some arithmetic tasks easer
$begin = microtime(true);

//write some awesome, fast PHP code here.
doSomething();

// Get the time at the final moment
$end = microtime(true);

echo "Time taken:", $end - $begin;

This is really simple and straightforward, but sometimes I use similar code to check the progress of import script or cron job. Example:

<?php

$db = getDatabase();

if (($handle = fopen('export.csv', "r")) !== FALSE) {
	$iRowNumber = 0;
	$iStartTime	= microtime(true);
	$iTotal		= count(file($sCSVFile));
	$aColumns	= array();

	while (($aRow = fgetcsv($handle, 0, ';')) !== FALSE) {
		$iRowNumber++;

				getDatabase()->queryExecute($sSQL);
		getProgress($iTotal, $iRowNumber, $iStartTime);
}
	echo "\nDone!\n";
}

The interesting part from the snippet above is the function getProgress().
It basically calculate the time difference and returns a formatted value, so you have easy readable feedback on elapsed time.

/**
 * Print progress information
 * @param integer $iTotal
 * @param integer $iCurrent
 * @param integer $iStartTime micro time
 */
function getProgress($iTotal, $iCurrent, $iStartTime) {
	printf(
		"\r%d of %d (%.1f%%) done. Time elapsed: %s",
		$iCurrent,
		$iTotal,
		100 * ($iCurrent / $iTotal),
		formatSeconds(microtime(true) - $iStartTime)
	);
}

/**
 * Returns formatted string as 01:20:15 000
 *
 * @param float $iSeconds seconds
 * @return string
 */
function formatSeconds($iSeconds) {
	$aNiceTime      = array('miliseconds' => 0, 'seconds' => 0, 'minutes' => 0, 'hours' => 0);
	$iDifference    = $iSeconds * 1000;

	$aPeriods		= array(
		'hours'         => 60*60*1000,
		'minutes'       => 60*1000,
		'seconds'       => 1000,
		'miliseconds'   => 1
	);

	foreach ($aPeriods as $sPeriod => $iMiliseconds) {
		$aNiceTime[$sPeriod]    = floor($iDifference / $iMiliseconds);
		$iDifference            = $iDifference % $iMiliseconds;
	}

	return sprintf(
		'%02d:%02d:%02d %03d',
		$aNiceTime['hours'],
		$aNiceTime['minutes'],
		$aNiceTime['seconds'],
		$aNiceTime['miliseconds']
	);
}

One thought on “Format microtime() to provide better feedback on the time elapsed

  1. Delyan Angelov

    IMHO, it is preferable, that prefixing a function name with ‘get’, is used only for idempotent functions, and not for procedures having side efects (IO), and that return no value at all.

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *