Welcome Guest, Not a member yet? Register   Sign In
Enhanced Benchmarking: aggregating marks
#1

[eluser]Unknown[/eluser]
I often want to benchmark an activity that occurs many times during a single request.

Example
Code:
foreach ($files as $file) {
     // S3: download profile file
     $this->benchmark->mark("s3_download_start");
     $this->s3->downloadFile($file);
     $this->benchmark->mark("s3_download_end");

     // PROFILE: import file to db
     $this->benchmark->mark("profile_import_start");
     $this->profile->import($file);
     $this->benchmark->mark("profile_import_end");
}

I'd like the profiler to show me the total time for each of the two activities, but (as you probably know), it only reports the time elapsed between the last calls to each activity's start and end.

Proposed Solution
I've extended the core Benchmark class and overridden the mark and elapsed_time methods as follows:

Code:
function mark($name)
{
if (!array_key_exists($name, $this->marker)) $this->marker[$name] = array();
$this->marker[$name][] = microtime(true);
}

function elapsed_time($point1 = '', $point2 = '', $decimals = 4)
{
if ($point1 == '')
{
  return '{elapsed_time}';
}

if ( ! isset($this->marker[$point1]))
{
  return '';
}

if ( ! isset($this->marker[$point2]))
{
  $this->marker[$point2] = array(microtime(true));
}

$iMSeconds = 0;
for ($iMark=0; $iMark<count($this->marker[$point1]); $iMark++){
  $iMSeconds += $this->marker[$point2][$iMark] - $this->marker[$point1][$iMark];
}

return number_format($iMSeconds, $decimals);
}

Questions
Is this a good approach? Better ideas? Problems? Would this be useful for others?
#2

[eluser]Unknown[/eluser]
Thanks, this was exactly what I needed to do some benchmarking!

As for it being added to a future version of CI, I suppose it kind of would make sense to make it optional to aggregate. Perhaps by adding an optional second parameter indicating whether one would want the tag to be aggregated, like so:
Code:
$this->benchmark->mark("mark_start", [TRUE|FALSE])

Regardless of how it would be implemented, it seems like a very good thing to add to the core.
#3

[eluser]Lechuss[/eluser]
Post it on Github.
#4

[eluser]CroNiX[/eluser]
Benchmarking just needs a unique starting identifier and ending identifier. You can easily use array keys to track that when using in a loop, just adding the key to the end of the start and end points and then tracking them so you can get at them later.
Code:
$keys = array();
foreach ($files as $key => $file) {
     $keys[] = $key;
     // S3: download profile file
     $this->benchmark->mark("s3_download_start_" . $key);
     $this->s3->downloadFile($file);
     $this->benchmark->mark("s3_download_end_" . $key);

     // PROFILE: import file to db
     $this->benchmark->mark("profile_import_start_" . $key);
     $this->profile->import($file);
     $this->benchmark->mark("profile_import_end_" . $key);
}

//Get the elapsed time for each timer
foreach ($keys as $key)
{
  echo "DL:$key: " . $this->benchmark->elapsed_time("s3_download_start_" . $key, "s3_download_end_" . $key) . '<br />';
  echo "Import:$key: " . $this->benchmark->elapsed_time("profile_import_start_" . $key, "profile_import_end_" . $key) . '<br />';
}




Theme © iAndrew 2016 - Forum software by © MyBB