1: <?php
2:
3: /*
4: * This file is part of the Symfony package.
5: *
6: * (c) Fabien Potencier <fabien@symfony.com>
7: *
8: * For the full copyright and license information, please view the LICENSE
9: * file that was distributed with this source code.
10: */
11:
12: namespace Symfony\Component\Stopwatch;
13:
14: /**
15: * Represents an Event managed by Stopwatch.
16: *
17: * @author Fabien Potencier <fabien@symfony.com>
18: */
19: class StopwatchEvent
20: {
21: /**
22: * @var StopwatchPeriod[]
23: */
24: private $periods;
25:
26: /**
27: * @var float
28: */
29: private $origin;
30:
31: /**
32: * @var string
33: */
34: private $category;
35:
36: /**
37: * @var float[]
38: */
39: private $started;
40:
41: /**
42: * Constructor.
43: *
44: * @param float $origin The origin time in milliseconds
45: * @param string $category The event category
46: *
47: * @throws \InvalidArgumentException When the raw time is not valid
48: */
49: public function __construct($origin, $category = null)
50: {
51: $this->origin = $this->formatTime($origin);
52: $this->category = is_string($category) ? $category : 'default';
53: $this->started = array();
54: $this->periods = array();
55: }
56:
57: /**
58: * Gets the category.
59: *
60: * @return string The category
61: */
62: public function getCategory()
63: {
64: return $this->category;
65: }
66:
67: /**
68: * Gets the origin.
69: *
70: * @return integer The origin in milliseconds
71: */
72: public function getOrigin()
73: {
74: return $this->origin;
75: }
76:
77: /**
78: * Starts a new event period.
79: *
80: * @return StopwatchEvent The event
81: */
82: public function start()
83: {
84: $this->started[] = $this->getNow();
85:
86: return $this;
87: }
88:
89: /**
90: * Stops the last started event period.
91: *
92: * @throws \LogicException When start wasn't called before stopping
93: *
94: * @return StopwatchEvent The event
95: *
96: * @throws \LogicException When stop() is called without a matching call to start()
97: */
98: public function stop()
99: {
100: if (!count($this->started)) {
101: throw new \LogicException('stop() called but start() has not been called before.');
102: }
103:
104: $this->periods[] = new StopwatchPeriod(array_pop($this->started), $this->getNow());
105:
106: return $this;
107: }
108:
109: /**
110: * Stops the current period and then starts a new one.
111: *
112: * @return StopwatchEvent The event
113: */
114: public function lap()
115: {
116: return $this->stop()->start();
117: }
118:
119: /**
120: * Stops all non already stopped periods.
121: */
122: public function ensureStopped()
123: {
124: while (count($this->started)) {
125: $this->stop();
126: }
127: }
128:
129: /**
130: * Gets all event periods.
131: *
132: * @return StopwatchPeriod[] An array of StopwatchPeriod instances
133: */
134: public function getPeriods()
135: {
136: return $this->periods;
137: }
138:
139: /**
140: * Gets the relative time of the start of the first period.
141: *
142: * @return integer The time (in milliseconds)
143: */
144: public function getStartTime()
145: {
146: return isset($this->periods[0]) ? $this->periods[0]->getStartTime() : 0;
147: }
148:
149: /**
150: * Gets the relative time of the end of the last period.
151: *
152: * @return integer The time (in milliseconds)
153: */
154: public function getEndTime()
155: {
156: return ($count = count($this->periods)) ? $this->periods[$count - 1]->getEndTime() : 0;
157: }
158:
159: /**
160: * Gets the duration of the events (including all periods).
161: *
162: * @return integer The duration (in milliseconds)
163: */
164: public function getDuration()
165: {
166: $total = 0;
167: foreach ($this->periods as $period) {
168: $total += $period->getDuration();
169: }
170:
171: return $this->formatTime($total);
172: }
173:
174: /**
175: * Gets the max memory usage of all periods.
176: *
177: * @return integer The memory usage (in bytes)
178: */
179: public function getMemory()
180: {
181: $memory = 0;
182: foreach ($this->periods as $period) {
183: if ($period->getMemory() > $memory) {
184: $memory = $period->getMemory();
185: }
186: }
187:
188: return $memory;
189: }
190:
191: /**
192: * Return the current time relative to origin.
193: *
194: * @return float Time in ms
195: */
196: protected function getNow()
197: {
198: return $this->formatTime(microtime(true) * 1000 - $this->origin);
199: }
200:
201: /**
202: * Formats a time.
203: *
204: * @param integer|float $time A raw time
205: *
206: * @return float The formatted time
207: *
208: * @throws \InvalidArgumentException When the raw time is not valid
209: */
210: private function formatTime($time)
211: {
212: if (!is_numeric($time)) {
213: throw new \InvalidArgumentException('The time must be a numerical value');
214: }
215:
216: return round($time, 1);
217: }
218: }
219: