33 private const FORMAT_VERSION = 2;
35 private static bool $enabled =
false;
36 private static int $timingStart = 0;
43 $time = $timings->getTotalTime();
44 $count = $timings->getCount();
50 $avg = $time / $count;
52 $group = $timings->getGroup();
53 $groups[$group][] = implode(
" ", [
58 "Violations: " . $timings->getViolations(),
59 "RecordId: " . $timings->getId(),
60 "ParentRecordId: " . ($timings->getParentId() ??
"none"),
61 "TimerId: " . $timings->getTimerId(),
62 "Ticks: " . $timings->getTicksActive(),
63 "Peak: " . $timings->getPeakTime(),
68 foreach(Utils::stringifyKeys($groups) as $groupName => $lines){
69 $result[] = $groupName;
70 foreach($lines as $line){
75 $result[] =
"# Version " . Server::getInstance()->getVersion();
76 $result[] =
"# " . Server::getInstance()->getName() .
" " . Server::getInstance()->getPocketMineVersion();
78 $result[] =
"# FormatVersion " . self::FORMAT_VERSION;
80 $sampleTime = hrtime(
true) - self::$timingStart;
81 $result[] =
"Sample time $sampleTime (" . ($sampleTime / 1000000000) .
"s)";
85 public static function isEnabled() : bool{
86 return self::$enabled;
89 public static function setEnabled(
bool $enable =
true) : void{
90 self::$enabled = $enable;
94 public static function getStartTime() : float{
95 return self::$timingStart;
98 public static function reload() : void{
99 TimingsRecord::reset();
101 self::$timingStart = hrtime(
true);
105 public static function tick(
bool $measure =
true) : void{
107 TimingsRecord::tick($measure);
111 private ?TimingsRecord $rootRecord =
null;
112 private int $timingDepth = 0;
118 private array $recordsByParent = [];
120 public function __construct(
121 private string $name,
122 private ?TimingsHandler $parent =
null,
123 private string $group = Timings::GROUP_MINECRAFT
126 public function getName() : string{ return $this->name; }
128 public function getGroup() : string{ return $this->group; }
130 public function startTiming() : void{
132 $this->internalStartTiming(hrtime(
true));
136 private function internalStartTiming(
int $now) : void{
137 if(++$this->timingDepth === 1){
138 if($this->parent !==
null){
139 $this->parent->internalStartTiming($now);
142 $current = TimingsRecord::getCurrentRecord();
143 if($current !==
null){
144 $record = $this->recordsByParent[spl_object_id($current)] ??
null;
145 if($record ===
null){
146 $record =
new TimingsRecord($this, $current);
147 $this->recordsByParent[spl_object_id($current)] = $record;
150 if($this->rootRecord ===
null){
151 $this->rootRecord =
new TimingsRecord($this,
null);
153 $record = $this->rootRecord;
155 $record->startTiming($now);
159 public function stopTiming() : void{
161 $this->internalStopTiming(hrtime(
true));
165 private function internalStopTiming(
int $now) : void{
166 if($this->timingDepth === 0){
172 if(--$this->timingDepth !== 0){
176 $record = TimingsRecord::getCurrentRecord();
177 $timerId = spl_object_id($this);
178 for(; $record !==
null && $record->getTimerId() !== $timerId; $record = TimingsRecord::getCurrentRecord()){
179 \GlobalLogger::get()->error(
"Timer \"" . $record->getName() .
"\" should have been stopped before stopping timer \"" . $this->name .
"\"");
180 $record->stopTiming($now);
182 $record?->stopTiming($now);
183 if($this->parent !==
null){
184 $this->parent->internalStopTiming($now);
195 public function time(\Closure $closure){
196 $this->startTiming();
207 public function reset() : void{
208 $this->rootRecord = null;
209 $this->recordsByParent = [];
210 $this->timingDepth = 0;