1<?php
2
3/*
4 * This file is part of Twig.
5 *
6 * (c) Fabien Potencier
7 *
8 * For the full copyright and license information, please view the LICENSE
9 * file that was distributed with this source code.
10 */
11
12namespace Twig\Profiler;
13
14/**
15 * @author Fabien Potencier <fabien@symfony.com>
16 *
17 * @final
18 */
19class Profile implements \IteratorAggregate, \Serializable
20{
21    const ROOT = 'ROOT';
22    const BLOCK = 'block';
23    const TEMPLATE = 'template';
24    const MACRO = 'macro';
25
26    private $template;
27    private $name;
28    private $type;
29    private $starts = [];
30    private $ends = [];
31    private $profiles = [];
32
33    public function __construct($template = 'main', $type = self::ROOT, $name = 'main')
34    {
35        $this->template = $template;
36        $this->type = $type;
37        $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name;
38        $this->enter();
39    }
40
41    public function getTemplate()
42    {
43        return $this->template;
44    }
45
46    public function getType()
47    {
48        return $this->type;
49    }
50
51    public function getName()
52    {
53        return $this->name;
54    }
55
56    public function isRoot()
57    {
58        return self::ROOT === $this->type;
59    }
60
61    public function isTemplate()
62    {
63        return self::TEMPLATE === $this->type;
64    }
65
66    public function isBlock()
67    {
68        return self::BLOCK === $this->type;
69    }
70
71    public function isMacro()
72    {
73        return self::MACRO === $this->type;
74    }
75
76    public function getProfiles()
77    {
78        return $this->profiles;
79    }
80
81    public function addProfile(self $profile)
82    {
83        $this->profiles[] = $profile;
84    }
85
86    /**
87     * Returns the duration in microseconds.
88     *
89     * @return int
90     */
91    public function getDuration()
92    {
93        if ($this->isRoot() && $this->profiles) {
94            // for the root node with children, duration is the sum of all child durations
95            $duration = 0;
96            foreach ($this->profiles as $profile) {
97                $duration += $profile->getDuration();
98            }
99
100            return $duration;
101        }
102
103        return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0;
104    }
105
106    /**
107     * Returns the memory usage in bytes.
108     *
109     * @return int
110     */
111    public function getMemoryUsage()
112    {
113        return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0;
114    }
115
116    /**
117     * Returns the peak memory usage in bytes.
118     *
119     * @return int
120     */
121    public function getPeakMemoryUsage()
122    {
123        return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0;
124    }
125
126    /**
127     * Starts the profiling.
128     */
129    public function enter()
130    {
131        $this->starts = [
132            'wt' => microtime(true),
133            'mu' => memory_get_usage(),
134            'pmu' => memory_get_peak_usage(),
135        ];
136    }
137
138    /**
139     * Stops the profiling.
140     */
141    public function leave()
142    {
143        $this->ends = [
144            'wt' => microtime(true),
145            'mu' => memory_get_usage(),
146            'pmu' => memory_get_peak_usage(),
147        ];
148    }
149
150    public function reset()
151    {
152        $this->starts = $this->ends = $this->profiles = [];
153        $this->enter();
154    }
155
156    public function getIterator()
157    {
158        return new \ArrayIterator($this->profiles);
159    }
160
161    public function serialize()
162    {
163        return serialize([$this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles]);
164    }
165
166    public function unserialize($data)
167    {
168        list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = unserialize($data);
169    }
170}
171
172class_alias('Twig\Profiler\Profile', 'Twig_Profiler_Profile');
173