*/ private static array $records = []; private static ?self $currentRecord = null; /** * @internal */ public static function reset() : void{ foreach(self::$records as $record){ $record->handler->reset(); } self::$records = []; self::$currentRecord = null; } /** * @return self[] * @phpstan-return array */ public static function getAll() : array{ return self::$records; } public static function tick(bool $measure = true) : void{ if($measure){ foreach(self::$records as $record){ if($record->curCount > 0){ if($record->curTickTotal > Server::TARGET_NANOSECONDS_PER_TICK){ $record->violations += (int) floor($record->curTickTotal / Server::TARGET_NANOSECONDS_PER_TICK); } $record->curTickTotal = 0; $record->curCount = 0; $record->ticksActive++; } } }else{ foreach(self::$records as $record){ $record->totalTime -= $record->curTickTotal; $record->count -= $record->curCount; $record->curTickTotal = 0; $record->curCount = 0; } } } private int $count = 0; private int $curCount = 0; private int $start = 0; private int $totalTime = 0; private int $curTickTotal = 0; private int $violations = 0; private int $ticksActive = 0; private int $peakTime = 0; public function __construct( //I'm not the biggest fan of this cycle, but it seems to be the most effective way to avoid leaking anything. private TimingsHandler $handler, private ?TimingsRecord $parentRecord ){ self::$records[spl_object_id($this)] = $this; } public function getId() : int{ return spl_object_id($this); } public function getParentId() : ?int{ return $this->parentRecord?->getId(); } public function getTimerId() : int{ return spl_object_id($this->handler); } public function getName() : string{ return $this->handler->getName(); } public function getGroup() : string{ return $this->handler->getGroup(); } public function getCount() : int{ return $this->count; } public function getCurCount() : int{ return $this->curCount; } public function getStart() : float{ return $this->start; } public function getTotalTime() : float{ return $this->totalTime; } public function getCurTickTotal() : float{ return $this->curTickTotal; } public function getViolations() : int{ return $this->violations; } public function getTicksActive() : int{ return $this->ticksActive; } public function getPeakTime() : int{ return $this->peakTime; } public function startTiming(int $now) : void{ $this->start = $now; self::$currentRecord = $this; } public function stopTiming(int $now) : void{ if($this->start == 0){ return; } if(self::$currentRecord !== $this){ if(self::$currentRecord === null){ //timings may have been stopped while this timer was running return; } throw new AssumptionFailedError("stopTiming() called on a non-current timer"); } self::$currentRecord = $this->parentRecord; $diff = $now - $this->start; $this->totalTime += $diff; $this->curTickTotal += $diff; ++$this->curCount; ++$this->count; $this->start = 0; if($diff > $this->peakTime){ $this->peakTime = $diff; } } public static function getCurrentRecord() : ?self{ return self::$currentRecord; } }