Magento 2 Documentation  2.3
Documentation for Magento 2 CMS v2.3 (December 2018)
Stat.php
Go to the documentation of this file.
1 <?php
9 
11 
12 class Stat
13 {
17  const ID = 'id';
18  const START = 'start';
19  const TIME = 'sum';
20  const COUNT = 'count';
21  const AVG = 'avg';
22  const REALMEM = 'realmem';
23  const REALMEM_START = 'realmem_start';
24  const EMALLOC = 'emalloc';
25  const EMALLOC_START = 'emalloc_start';
29  protected $_timers = [];
30 
40  public function start($timerId, $time, $realMemory, $emallocMemory)
41  {
42  if (empty($this->_timers[$timerId])) {
43  $this->_timers[$timerId] = [
44  self::START => false,
45  self::TIME => 0,
46  self::COUNT => 0,
47  self::REALMEM => 0,
48  self::EMALLOC => 0,
49  ];
50  }
51 
52  $this->_timers[$timerId][self::REALMEM_START] = $realMemory;
53  $this->_timers[$timerId][self::EMALLOC_START] = $emallocMemory;
54  $this->_timers[$timerId][self::START] = $time;
55  $this->_timers[$timerId][self::COUNT]++;
56  }
57 
68  public function stop($timerId, $time, $realMemory, $emallocMemory)
69  {
70  if (empty($this->_timers[$timerId])) {
71  throw new \InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId));
72  }
73 
74  $this->_timers[$timerId][self::TIME] += $time - $this->_timers[$timerId]['start'];
75  $this->_timers[$timerId][self::START] = false;
76  $this->_timers[$timerId][self::REALMEM] += $realMemory;
77  $this->_timers[$timerId][self::REALMEM] -= $this->_timers[$timerId][self::REALMEM_START];
78  $this->_timers[$timerId][self::EMALLOC] += $emallocMemory;
79  $this->_timers[$timerId][self::EMALLOC] -= $this->_timers[$timerId][self::EMALLOC_START];
80  }
81 
89  public function get($timerId)
90  {
91  if (empty($this->_timers[$timerId])) {
92  throw new \InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId));
93  }
94  return $this->_timers[$timerId];
95  }
96 
105  public function fetch($timerId, $key)
106  {
107  if ($key === self::ID) {
108  return $timerId;
109  }
110  if (empty($this->_timers[$timerId])) {
111  throw new \InvalidArgumentException(sprintf('Timer "%s" doesn\'t exist.', $timerId));
112  }
113  /* AVG = TIME / COUNT */
114  $isAvg = $key == self::AVG;
115  if ($isAvg) {
116  $key = self::TIME;
117  }
118  if (!isset($this->_timers[$timerId][$key])) {
119  throw new \InvalidArgumentException(sprintf('Timer "%s" doesn\'t have value for "%s".', $timerId, $key));
120  }
121  $result = $this->_timers[$timerId][$key];
122  if ($key == self::TIME && $this->_timers[$timerId][self::START] !== false) {
123  $result += microtime(true) - $this->_timers[$timerId][self::START];
124  }
125  if ($isAvg) {
126  $count = $this->_timers[$timerId][self::COUNT];
127  if ($count) {
128  $result = $result / $count;
129  }
130  }
131  return $result;
132  }
133 
140  public function clear($timerId = null)
141  {
142  if ($timerId) {
143  unset($this->_timers[$timerId]);
144  } else {
145  $this->_timers = [];
146  }
147  }
148 
156  public function getFilteredTimerIds(array $thresholds = null, $filterPattern = null)
157  {
158  $timerIds = $this->_getOrderedTimerIds();
159  if (!$thresholds && !$filterPattern) {
160  return $timerIds;
161  }
162  $thresholds = (array)$thresholds;
163  $result = [];
164  foreach ($timerIds as $timerId) {
165  /* Filter by pattern */
166  if ($filterPattern && !preg_match($filterPattern, $timerId)) {
167  continue;
168  }
169  /* Filter by thresholds */
170  $match = true;
171  foreach ($thresholds as $fetchKey => $minMatchValue) {
172  $match = $this->fetch($timerId, $fetchKey) >= $minMatchValue;
173  if ($match) {
174  break;
175  }
176  }
177  if ($match) {
178  $result[] = $timerId;
179  }
180  }
181  return $result;
182  }
183 
189  protected function _getOrderedTimerIds()
190  {
191  $timerIds = array_keys($this->_timers);
192  if (count($timerIds) <= 2) {
193  /* No sorting needed */
194  return $timerIds;
195  }
196 
197  /* Prepare PCRE once to use it inside the loop body */
198  $nestingSep = preg_quote(Profiler::NESTING_SEPARATOR, '/');
199  $patternLastTimerId = '/' . $nestingSep . '(?:.(?!' . $nestingSep . '))+$/';
200 
201  $prevTimerId = $timerIds[0];
202  $result = [$prevTimerId];
203  for ($i = 1; $i < count($timerIds); $i++) {
204  $timerId = $timerIds[$i];
205  /* Skip already added timer */
206  if (!$timerId) {
207  continue;
208  }
209  /* Loop over all timers that need to be closed under previous timer */
210  while (strpos($timerId, $prevTimerId . Profiler::NESTING_SEPARATOR) !== 0) {
211  /* Add to result all timers nested in the previous timer */
212  for ($j = $i + 1; $j < count($timerIds); $j++) {
213  if (strpos($timerIds[$j], $prevTimerId . Profiler::NESTING_SEPARATOR) === 0) {
214  $result[] = $timerIds[$j];
215  /* Mark timer as already added */
216  $timerIds[$j] = null;
217  }
218  }
219  /* Go to upper level timer */
220  $count = 0;
221  $prevTimerId = preg_replace($patternLastTimerId, '', $prevTimerId, -1, $count);
222  /* Break the loop if no replacements was done. It is possible when we are */
223  /* working with top level (root) item */
224  if (!$count) {
225  break;
226  }
227  }
228  /* Add current timer to the result */
229  $result[] = $timerId;
230  $prevTimerId = $timerId;
231  }
232  return $result;
233  }
234 }
getFilteredTimerIds(array $thresholds=null, $filterPattern=null)
Definition: Stat.php:156
$count
Definition: recent.phtml:13
stop($timerId, $time, $realMemory, $emallocMemory)
Definition: Stat.php:68
$i
Definition: gallery.phtml:31
start($timerId, $time, $realMemory, $emallocMemory)
Definition: Stat.php:40