Permalink
Browse files

Added the profiler, which doesn't work yet. The ProfilerTimer is full…

…y tested though.
  • Loading branch information...
1 parent 6844605 commit 1811973a6f0e8c39b6a774298a9fb1dec4aa5838 @enyo committed Apr 19, 2011
View
1 .gitignore
@@ -0,0 +1 @@
+/nbproject/private/
View
59 library/Profiler/Profile.php
@@ -0,0 +1,59 @@
+<?php
+
+/**
+ * This file contains the Profile definition.
+ *
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ **/
+
+
+/**
+ * The abstract Profile class is very small, and only a static wrapper for a specific
+ * Profiler implementation.
+ * All classes in the library use this class to profile their actions, so it gets included
+ * even if you do not set a profiler. This is the reason I decided to keep this class
+ * really simple, so there is nearly no overhead.
+ *
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ */
+abstract class Profile {
+
+ /**
+ * @var Profiler
+ */
+ protected static $profiler;
+
+
+ /**
+ * @param Profiler $profiler
+ */
+ public static function setProfiler($profiler) {
+ self::$profiler = $profiler;
+ }
+
+
+ /**
+ * Reroutes to self::$profiler->start()
+ * @param string $context
+ * @param string $section
+ * @see $profiler
+ */
+ public static function start($context, $section = null) {
+ if (self::$profiler) self::$profiler->start($context, $section);
+ }
+
+
+ /**
+ * Reroutes to self::$profiler->stop()
+ * @see $profiler
+ */
+ public static function stop() {
+ if (self::$profiler) self::$profiler->stop();
+ }
+
+
+}
View
66 library/Profiler/Profiler.php
@@ -0,0 +1,66 @@
+<?php
+
+/**
+ * This file contains the Profiler definition.
+ *
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ */
+/**
+ * Including the static class Profile
+ */
+require_class('Profile', 'Profiler');
+
+/**
+ * Including the Timer
+ */
+require_class('ProfilerTimer', 'Profiler');
+
+
+/**
+ * Normally you don't use an instance of Profiler to profile your app, but you set a Profiler instance
+ * to the static Profile class.
+ *
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ */
+class Profiler {
+
+ /**
+ * @var float
+ */
+ protected $totalStartTime;
+ /**
+ *
+ * @var array
+ */
+ protected $timerStack = array();
+ /**
+ *
+ * @var array
+ */
+ protected $times = array();
+
+ /**
+ * The profiler starts to profile as soon as it is instanciated.
+ */
+ public function __construct() {
+ $this->totalStartTime = microtime(true);
+ }
+
+ public function start($context, $section) {
+ if (count($this->timerStack) !== 0) {
+ $lastTimer = end($this->timerStack);
+ $lastTimer->pause();
+ }
+ $this->timerStack[] = new ProfilerTimer();
+ }
+
+ public function stop() {
+ $lastTimer = end($this->timerStack);
+ $lastTimer;
+ }
+
+}
View
118 library/Profiler/ProfilerTimer.php
@@ -0,0 +1,118 @@
+<?php
+
+/**
+ * This file contains the ProfilerTimer definition, which is the actual class that
+ * times parts of the program.
+ *
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ */
+
+/**
+ * The actual timer that gets instantiated and stored every time the profiler gets invoked.
+ * @author Matthias Loitsch <matthias@loitsch.com>
+ * @copyright Copyright (c) 2010, Matthias Loitsch
+ * @package Profiler
+ */
+class ProfilerTimer {
+
+ /**
+ * @var float
+ */
+ private $startTime;
+ /**
+ * @var float
+ */
+ private $endTime;
+ /**
+ * @var float
+ */
+ private $duration;
+ /**
+ * @var float
+ */
+ private $pauseStartTime;
+ /**
+ * @var float
+ */
+ private $totalPauseDuration = 0.0;
+
+ /**
+ * Sets the startTime
+ */
+ public function __construct() {
+ $this->startTime = microtime(true);
+ }
+
+ /**
+ * Sets the endtime, and calculates the duration
+ */
+ public function end() {
+ $this->resume();
+ $this->endTime = microtime(true);
+ $this->duration = $this->endTime - $this->startTime;
+ }
+
+ /**
+ * @return float
+ */
+ public function getStartTime() {
+ return $this->startTime;
+ }
+
+ /**
+ * @return float
+ */
+ public function getEndTime() {
+ return $this->endTime;
+ }
+
+ /**
+ * @return float
+ */
+ public function getDuration() {
+ if ($this->duration === null) return null;
+ return $this->duration - $this->totalPauseDuration;
+ }
+
+ /**
+ * @return float
+ */
+ public function getPauseStartTime() {
+ return $this->pauseStartTime;
+ }
+
+ /**
+ * @return float
+ */
+ public function getTotalPauseDuration() {
+ return $this->totalPauseDuration;
+ }
+
+ /**
+ * Whether the timer is paused or not.
+ * @return bool
+ */
+ public function isPaused() {
+ return $this->pauseStartTime !== null;
+ }
+
+ /**
+ * Pauses the timer
+ */
+ public function pause() {
+ if ( ! $this->isPaused()) $this->pauseStartTime = microtime(true);
+ }
+
+ /**
+ * Resumes the timer
+ */
+ public function resume() {
+ if ($this->isPaused()) {
+ $this->totalPauseDuration += microtime(true) - $this->pauseStartTime;
+ $this->pauseStartTime = null;
+ }
+ }
+
+}
View
147 phpunit/library/Profiler/ProfilerTimerTest.php
@@ -0,0 +1,147 @@
+<?php
+
+require_once 'PHPUnit/Framework.php';
+
+require_once dirname(__FILE__) . '/../../../library/Profiler/ProfilerTimer.php';
+
+/**
+ * Test class for ProfilerTimer.
+ * Generated by PHPUnit on 2011-04-19 at 14:02:29.
+ */
+class ProfilerTimerTest extends PHPUnit_Framework_TestCase {
+
+ /**
+ * @var ProfilerTimer
+ */
+ protected $profilerTimer;
+
+ /**
+ * Sets up the fixture, for example, opens a network connection.
+ * This method is called before a test is executed.
+ */
+ protected function setUp() {
+ $this->profilerTimer = new ProfilerTimer();
+ }
+
+ /**
+ * Tears down the fixture, for example, closes a network connection.
+ * This method is called after a test is executed.
+ */
+ protected function tearDown() {
+
+ }
+
+ /**
+ * @covers ProfilerTimer::__construct
+ * @covers ProfilerTimer::getStartTime
+ */
+ public function testConstructorSetsStartTime() {
+ $testProfilerTimer = new ProfilerTimer();
+ self::assertEquals(microtime(true), $testProfilerTimer->getStartTime(), 'The microtime should be nearly the same. If this test fails, try to run again.', 0.01);
+ }
+
+ /**
+ * @covers ProfilerTimer::end
+ * @covers ProfilerTimer::getEndTime
+ */
+ public function testEnd() {
+ usleep(5000);
+ $this->profilerTimer->end();
+ self::assertEquals(microtime(true), $this->profilerTimer->getEndTime(), 'The microtime should be nearly the same. If this test fails, try to run again.', 0.001);
+ }
+
+ /**
+ * @covers ProfilerTimer::end
+ * @covers ProfilerTimer::getDuration
+ */
+ public function testEndSetsDuration() {
+ usleep(5000);
+ $this->profilerTimer->end();
+ self::assertGreaterThanOrEqual(0.005, $this->profilerTimer->getDuration());
+ }
+
+ /**
+ * @covers ProfilerTimer::getDuration
+ */
+ public function testGetDurationReturnsNullIfNotFinished() {
+ self::assertNull($this->profilerTimer->getDuration());
+ }
+
+ /**
+ * @covers ProfilerTimer::isPaused
+ * @covers ProfilerTimer::getPauseStartTime
+ */
+ public function testIsPaused() {
+ self::assertSame(false, $this->profilerTimer->isPaused());
+ self::assertNull($this->profilerTimer->getPauseStartTime());
+ $this->profilerTimer->pause();
+ self::assertSame(true, $this->profilerTimer->isPaused());
+ }
+
+ /**
+ * @covers ProfilerTimer::pause
+ */
+ public function testPauseSetsPauseStartTime() {
+ $this->profilerTimer->pause();
+ self::assertEquals(microtime(true), $this->profilerTimer->getPauseStartTime(), '', 0.01);
+ }
+
+ /**
+ * @covers ProfilerTimer::resume
+ */
+ public function testResume() {
+ $this->profilerTimer->pause();
+ self::assertSame(true, $this->profilerTimer->isPaused());
+ $this->profilerTimer->resume();
+ self::assertSame(false, $this->profilerTimer->isPaused());
+ self::assertNull($this->profilerTimer->getPauseStartTime());
+ }
+
+ /**
+ * @covers ProfilerTimer::getTotalPauseDuration
+ */
+ public function testGetTotalPauseDuration() {
+ $this->profilerTimer->pause();
+ usleep(5000);
+ $this->profilerTimer->resume();
+ self::assertGreaterThanOrEqual(0.005, $this->profilerTimer->getTotalPauseDuration());
+ $this->profilerTimer->pause();
+ usleep(5000);
+ $this->profilerTimer->resume();
+ self::assertGreaterThanOrEqual(0.01, $this->profilerTimer->getTotalPauseDuration());
+ }
+
+ /**
+ * @covers ProfilerTimer::pause
+ */
+ public function testPauseDoesNothingIfAlreadyPaused() {
+ $this->profilerTimer->pause();
+ $firstPausetime = $this->profilerTimer->getPauseStartTime();
+ usleep(50);
+ $this->profilerTimer->pause();
+ self::assertSame($firstPausetime, $this->profilerTimer->getPauseStartTime());
+ }
+
+
+ /**
+ * @covers ProfilerTimer::getDuration
+ */
+ public function testGetTotalDurationSubstractsPause() {
+ $this->profilerTimer->pause();
+ usleep(500000); // sleeps 0.5 s
+ $this->profilerTimer->resume();
+ $this->profilerTimer->end();
+ self::assertEquals($this->profilerTimer->getEndTime() - $this->profilerTimer->getStartTime() - 0.5, $this->profilerTimer->getDuration(), '', 0.001);
+ }
+
+ /**
+ * @covers ProfilerTimer::end
+ */
+ public function testEndResumesTimerFirst() {
+ $this->profilerTimer->pause();
+ self::assertTrue($this->profilerTimer->isPaused());
+ $this->profilerTimer->end();
+ self::assertFalse($this->profilerTimer->isPaused());
+ }
+
+}

0 comments on commit 1811973

Please sign in to comment.