00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00018 abstract class STimer {
00019 private static $TIMES = array();
00020 private static $SPANS = array();
00021 private static $AVG_SPANS = array();
00022
00023 private static $ENABLED = false;
00024 private static $ISREGISTERED = false;
00025
00026 private static $DISPLAY_MARKERS = true;
00027 private static $DISPLAY_SPANS = false;
00028
00036 public static function dump() {
00037 $prevTime = self::$TIMES[0]['time'];
00038 $startTime = $prevTime;
00039 if(count(self::$SPANS) > 0) {
00040 $i = 0;
00041 $total = 0;
00042 foreach(self::$SPANS as $name => $info) {
00043 if(!isset($info['end']))
00044 continue;
00045 print "$name: ";
00046 print number_format(($info['start'] - $startTime) * 1000, 4) . " ms, ";
00047 print number_format(($info['end'] - $startTime) * 1000, 4) . " ms, ";
00048 print number_format(($info['end'] - $info['start']) * 1000, 4) . " ms\n";
00049 $total += ($info['end'] - $info['start']);
00050
00051 $i++;
00052 }
00053 print "Total: " . number_format($total * 1000, 4) . "\n";
00054 }
00055 }
00056
00064 public static function dumpAsXML() {
00065 if(!self::$ENABLED)
00066 return;
00067
00068 self::mark('__END__');
00069
00070 $prevTime = self::$TIMES[0]['time'];
00071 $startTime = $prevTime;
00072
00073 $xml = '<STimer>';
00074
00075 if(count(self::$TIMES) > 1) {
00076 $xml .= '<markers>';
00077
00078 for($i = 1; $i < count(self::$TIMES); $i++) {
00079 $xml .= '<marker>';
00080 $xml .= '<name>' . self::$TIMES[$i]['name'] . '</name>';
00081 $xml .= '<duration>' . number_format((self::$TIMES[$i]['time'] - $prevTime) * 1000, 4) . " ms" . '</duration>';
00082 $xml .= '<elapsed>' . number_format((self::$TIMES[$i]['time'] - $startTime) * 1000, 4) . " ms" . '</elapsed>';
00083 $xml .= '</marker>';
00084 $prevTime = self::$TIMES[$i]['time'];
00085 }
00086
00087 $xml .= '</markers>';
00088 }
00089
00090 if(count(self::$SPANS) > 0) {
00091 $xml .= '<spans>';
00092
00093 $total = 0;
00094 foreach(self::$SPANS as $name => $info) {
00095 if(!isset($info['end']))
00096 continue;
00097 $xml .= '<span>';
00098 $xml .= '<name>' . $name . '</name>';
00099 $xml .= '<start>' . number_format(($info['start'] - $startTime) * 1000, 4) . " ms" . '</start>';
00100 $xml .= '<end>' . number_format(($info['end'] - $startTime) * 1000, 4) . " ms" . '</end>';
00101 $xml .= '<duration>' . number_format(($info['end'] - $info['start']) * 1000, 4) . " ms" . '</duration>';
00102 $xml .= '</span>';
00103 $total += ($info['end'] - $info['start']);
00104 }
00105 $xml .= '</spans>';
00106 $xml .= '<spanTotal>' . number_format($total * 1000, 4) . '</spanTotal>';
00107 }
00108
00109 if(count(self::$AVG_SPANS) > 0) {
00110 $xml .= '<averageSpans>';
00111 $i = 0;
00112 $totalMin = 0;
00113 $totalMax = 0;
00114 $totalDur = 0;
00115 $totalCount = 0;
00116 $totalAvg = 0;
00117 $avgMin = 0;
00118 $avgMax = 0;
00119 $avgAvg = 0;
00120 $avgDur = 0;
00121 foreach(self::$AVG_SPANS as $name => $info) {
00122 if(!isset($info['end']) || count($info['start']) != count($info['end']))
00123 continue;
00124 $sum = 0;
00125 $min = $info['end'][0] - $info['start'][0];
00126 $max = $min;
00127 foreach($info['start'] as $j => $start) {
00128 $delta = ($info['end'][$j] - $start);
00129 if($delta < $min)
00130 $min = $delta;
00131 if($delta > $max)
00132 $max = $delta;
00133 $sum += $delta;
00134 }
00135 $spanTotal = $sum;
00136 $sum /= count($info['start']);
00137 $xml .= '<span>';
00138 $xml .= '<name>' . $name . '</name>';
00139 $xml .= '<min>' . number_format($min * 1000, 4) . " ms" . '</min>';
00140 $xml .= '<max>' . number_format($max * 1000, 4) . " ms" . '</max>';
00141 $xml .= '<sum>' . number_format($sum * 1000, 4) . " ms" . '</sum>';
00142 $xml .= '<spanTotal>' . number_format($spanTotal * 1000, 4) . " ms" . '</spanTotal>';
00143 $xml .= '<count>' . count($info['start']) . '</count>';
00144 $xml .= '</span>';
00145 $totalMin += $min;
00146 $totalMax += $max;
00147 $totalDur += $spanTotal;
00148 $totalCount += count($info['start']);
00149 $totalAvg += $sum;
00150
00151 $avgMin += ($min * count($info['start']));
00152 $avgMax += ($max * count($info['start']));
00153 $avgAvg += ($sum * count($info['start']));
00154 $avgDur += ($spanTotal * count($info['start']));
00155
00156 $i++;
00157 }
00158
00159 $avgMin /= $totalCount;
00160 $avgMax /= $totalCount;
00161 $avgAvg /= $totalCount;
00162 $avgDur /= $totalCount;
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182 $xml .= '</averageSpans>';
00183 }
00184
00185
00186 $xml .= '</STimer>';
00187
00188 return $xml;
00189 }
00190
00198 public static function dumpAsArray() {
00199 if(!self::$ENABLED)
00200 return;
00201
00202 self::mark('__END__');
00203
00204 $prevTime = self::$TIMES[0]['time'];
00205 $startTime = $prevTime;
00206
00207 $out = array();
00208
00209 if(count(self::$TIMES) > 1) {
00210 $out['markers'] = array();
00211
00212 for($i = 1; $i < count(self::$TIMES); $i++) {
00213 $marker = array();
00214 $marker['name'] = self::$TIMES[$i]['name'];
00215 $marker['duration'] = number_format((self::$TIMES[$i]['time'] - $prevTime) * 1000, 4) . " ms";
00216 $marker['elapsed'] = number_format((self::$TIMES[$i]['time'] - $startTime) * 1000, 4) . " ms";
00217 $out['markers'][] = $marker;
00218 $prevTime = self::$TIMES[$i]['time'];
00219 }
00220 }
00221
00222 if(count(self::$SPANS) > 0) {
00223 $out['spans'] = array();
00224
00225 $total = 0;
00226 foreach(self::$SPANS as $name => $info) {
00227 if(!isset($info['end']))
00228 continue;
00229 $span = array();
00230 $span['name'] = $name;
00231 $span['start'] = number_format(($info['start'] - $startTime) * 1000, 4) . " ms";
00232 $span['end'] = number_format(($info['end'] - $startTime) * 1000, 4) . " ms";
00233 $span['duration'] = number_format(($info['end'] - $info['start']) * 1000, 4) . " ms";
00234 $out['spans'][] = $span;
00235 $total += ($info['end'] - $info['start']);
00236 }
00237 $out['spanTotal'] = number_format($total * 1000, 4);
00238 }
00239
00240 return $out;
00241 }
00242
00250 public static function getTime() {
00251 return array_sum(explode(' ', microtime()));
00252 }
00253
00262 public static function mark($name) {
00263 if(!self::$ENABLED)
00264 return;
00265 array_push(self::$TIMES, array(
00266 'name' => $name,
00267 'time' => array_sum(explode(' ', microtime()))
00268 ));
00269 return true;
00270 }
00271
00280 public static function start($name) {
00281 if(!self::$ENABLED)
00282 return;
00283 self::$SPANS[$name] = array('start' => array_sum(explode(' ', microtime())));
00284 }
00285
00294 public static function end($name) {
00295 if(!self::$ENABLED)
00296 return;
00297 self::$SPANS[$name]['end'] = array_sum(explode(' ', microtime()));
00298 }
00299
00308 public static function startAvg($name) {
00309 if(!self::$ENABLED)
00310 return;
00311
00312 self::$AVG_SPANS[$name]['start'][] = array_sum(explode(' ', microtime()));
00313 }
00314
00323 public static function endAvg($name) {
00324 if(!self::$ENABLED)
00325 return;
00326
00327 self::$AVG_SPANS[$name]['end'][] = array_sum(explode(' ', microtime()));
00328 }
00329
00338 public static function enable($enable) {
00339 self::$ENABLED = $enable ? true : false;
00340 if($enable) {
00341 if(!self::$ISREGISTERED) {
00342 register_shutdown_function(array('STimer', '_printTimes'));
00343 self::mark('__START__');
00344 }
00345 else
00346 self::$ISREGISTERED = true;
00347 }
00348 return true;
00349 }
00350
00358 public static function isEnabled() {
00359 return self::$ENABLED;
00360 }
00361
00370 public static function displayMarkers($display) {
00371 self::$DISPLAY_MARKERS = $display ? true : false;
00372 }
00373
00382 public static function displaySpans($display) {
00383 self::$DISPLAY_SPANS = $display ? true : false;
00384 }
00385
00393 public static function _printTimes() {
00394 if(!self::$ENABLED)
00395 return;
00396
00397 self::mark('__END__');
00398
00399 $prevTime = self::$TIMES[0]['time'];
00400 $startTime = $prevTime;
00401
00402 if(count(self::$TIMES) > 1) {
00403 $markerTable = new TKTable();
00404 $markerTable->addTextTo('header', "Marker");
00405 $markerTable->addTextTo('header', "Duration");
00406 $markerTable->addTextTo('header', "Elapsed");
00407
00408 for($i = 1; $i < count(self::$TIMES); $i++) {
00409 $markerTable->addText(self::$TIMES[$i]['name'],
00410 array('style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00411 $markerTable->addText(number_format((self::$TIMES[$i]['time'] - $prevTime) * 1000, 4) . " ms");
00412 $markerTable->addText(number_format((self::$TIMES[$i]['time'] - $startTime) * 1000, 4) . " ms");
00413 $prevTime = self::$TIMES[$i]['time'];
00414
00415 if($i < count(self::$TIMES) - 1)
00416 $markerTable->addRow();
00417 }
00418
00419 print $markerTable->render();
00420 }
00421
00422 if(count(self::$SPANS) > 0) {
00423 $spanTable = new TKTable();
00424 $spanTable->addTextTo('header', "Span");
00425 $spanTable->addTextTo('header', "Start");
00426 $spanTable->addTextTo('header', "End");
00427 $spanTable->addTextTo('header', "Duration");
00428
00429 $i = 0;
00430 $total = 0;
00431 foreach(self::$SPANS as $name => $info) {
00432 if(!isset($info['end']))
00433 continue;
00434 $spanTable->addText($name, array('style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00435 $spanTable->addText(number_format(($info['start'] - $startTime) * 1000, 4) . " ms");
00436 $spanTable->addText(number_format(($info['end'] - $startTime) * 1000, 4) . " ms");
00437 $spanTable->addText(number_format(($info['end'] - $info['start']) * 1000, 4) . " ms");
00438 $total += ($info['end'] - $info['start']);
00439
00440 if($i < count(self::$SPANS) - 1)
00441 $spanTable->addRow();
00442
00443 $i++;
00444 }
00445 $spanTable->addRow();
00446 $spanTable->addText('Total:', array('colspan' => 3,
00447 'style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00448 $spanTable->addText(number_format($total * 1000, 4));
00449 print $spanTable->render();
00450 }
00451
00452 if(count(self::$AVG_SPANS) > 0) {
00453 $spanTable = new TKTable();
00454 $spanTable->addTextTo('header', "Span");
00455 $spanTable->addTextTo('header', "Min Duration");
00456 $spanTable->addTextTo('header', "Max Duration");
00457 $spanTable->addTextTo('header', "Avg Duration");
00458 $spanTable->addTextTo('header', "Total Duration");
00459 $spanTable->addTextTo('header', "Count");
00460
00461 $i = 0;
00462 $totalMin = 0;
00463 $totalMax = 0;
00464 $totalDur = 0;
00465 $totalCount = 0;
00466 $totalAvg = 0;
00467 $avgMin = 0;
00468 $avgMax = 0;
00469 $avgAvg = 0;
00470 $avgDur = 0;
00471 foreach(self::$AVG_SPANS as $name => $info) {
00472 if(!isset($info['end']) || count($info['start']) != count($info['end']))
00473 continue;
00474 $sum = 0;
00475 $min = $info['end'][0] - $info['start'][0];
00476 $max = $min;
00477 foreach($info['start'] as $j => $start) {
00478 $delta = ($info['end'][$j] - $start);
00479 if($delta < $min)
00480 $min = $delta;
00481 if($delta > $max)
00482 $max = $delta;
00483 $sum += $delta;
00484 }
00485 $spanTotal = $sum;
00486 $sum /= count($info['start']);
00487 $spanTable->addText($name, array('style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00488 $spanTable->addText(number_format($min * 1000, 4) . " ms");
00489 $spanTable->addText(number_format($max * 1000, 4) . " ms");
00490 $spanTable->addText(number_format($sum * 1000, 4) . " ms");
00491 $spanTable->addText(number_format($spanTotal * 1000, 4) . " ms");
00492 $spanTable->addText(count($info['start']));
00493 $totalMin += $min;
00494 $totalMax += $max;
00495 $totalDur += $spanTotal;
00496 $totalCount += count($info['start']);
00497 $totalAvg += $sum;
00498
00499 $avgMin += ($min * count($info['start']));
00500 $avgMax += ($max * count($info['start']));
00501 $avgAvg += ($sum * count($info['start']));
00502 $avgDur += ($spanTotal * count($info['start']));
00503
00504 if($i < count(self::$AVG_SPANS) - 1)
00505 $spanTable->addRow();
00506
00507 $i++;
00508 }
00509
00510 $spanTable->addRow();
00511 $spanTable->addText('Total:', array('style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00512 $spanTable->addText(number_format($totalMin * 1000, 4) . " ms");
00513 $spanTable->addText(number_format($totalMax * 1000, 4) . " ms");
00514 $spanTable->addText(number_format($totalAvg * 1000, 4) . " ms");
00515 $spanTable->addText(number_format($totalDur * 1000, 4) . " ms");
00516 $spanTable->addText($totalCount);
00517
00518 if($totalCount == 0) {
00519 $avgMin = "???";
00520 $avgMax = "???";
00521 $avgAvg = "???";
00522 $avgDur = "???";
00523 }
00524 else {
00525 $avgMin /= $totalCount;
00526 $avgMax /= $totalCount;
00527 $avgAvg /= $totalCount;
00528 $avgDur /= $totalCount;
00529 $avgMin = number_format($avgMin * 1000, 4) . " ms";
00530 $avgMax = number_format($avgMax * 1000, 4) . " ms";
00531 $avgAvg = number_format($avgAvg * 1000, 4) . " ms";
00532 $avgDur = number_format($avgDur * 1000, 4) . " ms";
00533 }
00534
00535 $spanTable->addRow();
00536 $spanTable->addText('Average:', array('style' => array('font-weight' => 'bold', 'text-align' => 'right')));
00537 $spanTable->addText($avgMin);
00538 $spanTable->addText($avgMax);
00539 $spanTable->addText($avgAvg);
00540 $spanTable->addText($avgDur);
00541 $spanTable->addText('N/A');
00542
00543 print $spanTable->render();
00544 }
00545 }
00546 }
00547
00548 ?>