From 077fac84bfebc35c0c8cf9d97ad9ae637f1eaca3 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 8 May 2023 16:27:46 +0100 Subject: [PATCH] Added aggregate timers for all world timings this allows timings list view to display totals for these sections. It does make the tree view a bit more annoying in some cases though. --- src/timings/Timings.php | 22 +------------ src/world/World.php | 18 ++++++----- src/world/WorldManager.php | 3 -- src/world/WorldTimings.php | 63 ++++++++++++++++++++++++++------------ 4 files changed, 55 insertions(+), 51 deletions(-) diff --git a/src/timings/Timings.php b/src/timings/Timings.php index 74fa40dde..70a2a03cf 100644 --- a/src/timings/Timings.php +++ b/src/timings/Timings.php @@ -87,14 +87,6 @@ abstract class Timings{ /** @var TimingsHandler */ public static $serverCommand; /** @var TimingsHandler */ - public static $worldLoad; - /** @var TimingsHandler */ - public static $worldSave; - /** @var TimingsHandler */ - public static $population; - /** @var TimingsHandler */ - public static $generationCallback; - /** @var TimingsHandler */ public static $permissibleCalculation; /** @var TimingsHandler */ public static $permissibleCalculationDiff; @@ -111,10 +103,6 @@ abstract class Timings{ /** @var TimingsHandler */ public static $playerCheckNearEntities; - /** @var TimingsHandler */ - public static $tickEntity; - /** @var TimingsHandler */ - public static $tickTileEntity; /** @var TimingsHandler */ public static $entityBaseTick; @@ -203,10 +191,6 @@ abstract class Timings{ self::$playerChunkSend = new TimingsHandler("Player Network Send - Chunks", self::$playerNetworkSend, group: self::GROUP_BREAKDOWN); self::$scheduler = new TimingsHandler("Scheduler"); self::$serverCommand = new TimingsHandler("Server Command"); - self::$worldLoad = new TimingsHandler("World Load"); - self::$worldSave = new TimingsHandler("World Save"); - self::$population = new TimingsHandler("World Population"); - self::$generationCallback = new TimingsHandler("World Generation Callback"); self::$permissibleCalculation = new TimingsHandler("Permissible Calculation"); self::$permissibleCalculationDiff = new TimingsHandler("Permissible Calculation - Diff", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN); self::$permissibleCalculationCallback = new TimingsHandler("Permissible Calculation - Callbacks", self::$permissibleCalculation, group: self::GROUP_BREAKDOWN); @@ -221,9 +205,6 @@ abstract class Timings{ self::$projectileMoveRayTrace = new TimingsHandler("Projectile Movement - Ray Tracing", self::$projectileMove, group: self::GROUP_BREAKDOWN); self::$playerCheckNearEntities = new TimingsHandler("checkNearEntities", group: self::GROUP_BREAKDOWN); - self::$tickEntity = new TimingsHandler("Entity Tick", group: self::GROUP_BREAKDOWN); - self::$tickTileEntity = new TimingsHandler("Block Entity Tick", group: self::GROUP_BREAKDOWN); - self::$entityBaseTick = new TimingsHandler("Entity Base Tick", group: self::GROUP_BREAKDOWN); self::$livingEntityBaseTick = new TimingsHandler("Entity Base Tick - Living", group: self::GROUP_BREAKDOWN); self::$itemEntityBaseTick = new TimingsHandler("Entity Base Tick - ItemEntity", group: self::GROUP_BREAKDOWN); @@ -272,7 +253,7 @@ abstract class Timings{ }else{ $displayName = self::shortenCoreClassName($entity::class, "pocketmine\\entity\\"); } - self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName, self::$tickEntity, group: self::GROUP_BREAKDOWN); + self::$entityTypeTimingMap[$entity::class] = new TimingsHandler("Entity Tick - " . $displayName, group: self::GROUP_BREAKDOWN); } return self::$entityTypeTimingMap[$entity::class]; @@ -282,7 +263,6 @@ abstract class Timings{ if(!isset(self::$tileEntityTypeTimingMap[$tile::class])){ self::$tileEntityTypeTimingMap[$tile::class] = new TimingsHandler( "Block Entity Tick - " . self::shortenCoreClassName($tile::class, "pocketmine\\block\\tile\\"), - self::$tickTileEntity, group: self::GROUP_BREAKDOWN ); } diff --git a/src/world/World.php b/src/world/World.php index 1803c03f1..ef62cb987 100644 --- a/src/world/World.php +++ b/src/world/World.php @@ -77,7 +77,6 @@ use pocketmine\promise\PromiseResolver; use pocketmine\scheduler\AsyncPool; use pocketmine\Server; use pocketmine\ServerConfigGroup; -use pocketmine\timings\Timings; use pocketmine\utils\AssumptionFailedError; use pocketmine\utils\Limits; use pocketmine\utils\ReversePriorityQueue; @@ -999,7 +998,6 @@ class World implements ChunkManager{ $this->timings->entityTick->startTiming(); //Update entities that need update - Timings::$tickEntity->startTiming(); foreach($this->updateEntities as $id => $entity){ if($entity->isClosed() || $entity->isFlaggedForDespawn() || !$entity->onUpdate($currentTick)){ unset($this->updateEntities[$id]); @@ -1008,7 +1006,6 @@ class World implements ChunkManager{ $entity->close(); } } - Timings::$tickEntity->stopTiming(); $this->timings->entityTick->stopTiming(); $this->timings->randomChunkUpdates->startTiming(); @@ -1439,10 +1436,15 @@ class World implements ChunkManager{ (new WorldSaveEvent($this))->call(); + $timings = $this->timings->syncDataSave; + $timings->startTiming(); + $this->provider->getWorldData()->setTime($this->time); $this->saveChunks(); $this->provider->getWorldData()->save(); + $timings->stopTiming(); + return true; } @@ -3248,7 +3250,8 @@ class World implements ChunkManager{ private function internalOrderChunkPopulation(int $chunkX, int $chunkZ, ?ChunkLoader $associatedChunkLoader, ?PromiseResolver $resolver) : Promise{ $chunkHash = World::chunkHash($chunkX, $chunkZ); - Timings::$population->startTiming(); + $timings = $this->timings->chunkPopulationOrder; + $timings->startTiming(); try{ for($xx = -1; $xx <= 1; ++$xx){ @@ -3305,7 +3308,7 @@ class World implements ChunkManager{ return $resolver->getPromise(); }finally{ - Timings::$population->stopTiming(); + $timings->stopTiming(); } } @@ -3314,7 +3317,8 @@ class World implements ChunkManager{ * @phpstan-param array $adjacentChunks */ private function generateChunkCallback(ChunkLockId $chunkLockId, int $x, int $z, Chunk $chunk, array $adjacentChunks, ChunkLoader $temporaryChunkLoader) : void{ - Timings::$generationCallback->startTiming(); + $timings = $this->timings->chunkPopulationCompletion; + $timings->startTiming(); $dirtyChunks = 0; for($xx = -1; $xx <= 1; ++$xx){ @@ -3383,7 +3387,7 @@ class World implements ChunkManager{ $this->drainPopulationRequestQueue(); } - Timings::$generationCallback->stopTiming(); + $timings->stopTiming(); } public function doChunkGarbageCollection() : void{ diff --git a/src/world/WorldManager.php b/src/world/WorldManager.php index 1124d513d..f056608d7 100644 --- a/src/world/WorldManager.php +++ b/src/world/WorldManager.php @@ -30,7 +30,6 @@ use pocketmine\event\world\WorldUnloadEvent; use pocketmine\lang\KnownTranslationFactory; use pocketmine\player\ChunkSelector; use pocketmine\Server; -use pocketmine\timings\Timings; use pocketmine\world\format\Chunk; use pocketmine\world\format\io\exception\CorruptedWorldException; use pocketmine\world\format\io\exception\UnsupportedWorldFormatException; @@ -391,7 +390,6 @@ class WorldManager{ } private function doAutoSave() : void{ - Timings::$worldSave->startTiming(); foreach($this->worlds as $world){ foreach($world->getPlayers() as $player){ if($player->spawned){ @@ -400,6 +398,5 @@ class WorldManager{ } $world->save(false); } - Timings::$worldSave->stopTiming(); } } diff --git a/src/world/WorldTimings.php b/src/world/WorldTimings.php index 5a51f920b..97ab70709 100644 --- a/src/world/WorldTimings.php +++ b/src/world/WorldTimings.php @@ -38,6 +38,7 @@ class WorldTimings{ public TimingsHandler $randomChunkUpdatesChunkSelection; public TimingsHandler $doChunkGC; public TimingsHandler $entityTick; + public TimingsHandler $tileTick; public TimingsHandler $doTick; public TimingsHandler $syncChunkSend; @@ -48,33 +49,55 @@ class WorldTimings{ public TimingsHandler $syncChunkLoadFixInvalidBlocks; public TimingsHandler $syncChunkLoadEntities; public TimingsHandler $syncChunkLoadTileEntities; + + public TimingsHandler $syncDataSave; public TimingsHandler $syncChunkSave; + public TimingsHandler $chunkPopulationOrder; + public TimingsHandler $chunkPopulationCompletion; + + /** + * @var TimingsHandler[] + * @phpstan-var array + */ + private static array $aggregators = []; + + private static function newTimer(string $worldName, string $timerName) : TimingsHandler{ + $aggregator = self::$aggregators[$timerName] ??= new TimingsHandler("Worlds - $timerName"); //displayed in Minecraft primary table + + //TODO: maybe a dedicated group per world would be better? + return new TimingsHandler("$worldName - $timerName", $aggregator, Timings::GROUP_BREAKDOWN); + } + public function __construct(World $world){ - $name = $world->getFolderName() . " - "; + $name = $world->getFolderName(); - $this->setBlock = new TimingsHandler($name . "setBlock", group: Timings::GROUP_BREAKDOWN); - $this->doBlockLightUpdates = new TimingsHandler($name . "Block Light Updates", group: Timings::GROUP_BREAKDOWN); - $this->doBlockSkyLightUpdates = new TimingsHandler($name . "Sky Light Updates", group: Timings::GROUP_BREAKDOWN); + $this->setBlock = self::newTimer($name, "Set Blocks"); + $this->doBlockLightUpdates = self::newTimer($name, "Block Light Updates"); + $this->doBlockSkyLightUpdates = self::newTimer($name, "Sky Light Updates"); - $this->doChunkUnload = new TimingsHandler($name . "Unload Chunks", group: Timings::GROUP_BREAKDOWN); - $this->scheduledBlockUpdates = new TimingsHandler($name . "Scheduled Block Updates", group: Timings::GROUP_BREAKDOWN); - $this->randomChunkUpdates = new TimingsHandler($name . "Random Chunk Updates", group: Timings::GROUP_BREAKDOWN); - $this->randomChunkUpdatesChunkSelection = new TimingsHandler($name . "Random Chunk Updates - Chunk Selection", group: Timings::GROUP_BREAKDOWN); - $this->doChunkGC = new TimingsHandler($name . "Garbage Collection", group: Timings::GROUP_BREAKDOWN); - $this->entityTick = new TimingsHandler($name . "Tick Entities", group: Timings::GROUP_BREAKDOWN); + $this->doChunkUnload = self::newTimer($name, "Unload Chunks"); + $this->scheduledBlockUpdates = self::newTimer($name, "Scheduled Block Updates"); + $this->randomChunkUpdates = self::newTimer($name, "Random Chunk Updates"); + $this->randomChunkUpdatesChunkSelection = self::newTimer($name, "Random Chunk Updates - Chunk Selection"); + $this->doChunkGC = self::newTimer($name, "Garbage Collection"); + $this->entityTick = self::newTimer($name, "Entity Tick"); + $this->tileTick = self::newTimer($name, "Block Entity Tick"); + $this->doTick = self::newTimer($name, "World Tick"); - Timings::init(); //make sure the timers we want are available - $this->syncChunkSend = new TimingsHandler($name . "Player Send Chunks", Timings::$playerChunkSend, group: Timings::GROUP_BREAKDOWN); - $this->syncChunkSendPrepare = new TimingsHandler($name . "Player Send Chunk Prepare", Timings::$playerChunkSend, group: Timings::GROUP_BREAKDOWN); + $this->syncChunkSend = self::newTimer($name, "Player Send Chunks"); + $this->syncChunkSendPrepare = self::newTimer($name, "Player Send Chunk Prepare"); - $this->syncChunkLoad = new TimingsHandler($name . "Chunk Load", Timings::$worldLoad, group: Timings::GROUP_BREAKDOWN); - $this->syncChunkLoadData = new TimingsHandler($name . "Chunk Load - Data", group: Timings::GROUP_BREAKDOWN); - $this->syncChunkLoadFixInvalidBlocks = new TimingsHandler($name . "Chunk Load - Fix Invalid Blocks", group: Timings::GROUP_BREAKDOWN); - $this->syncChunkLoadEntities = new TimingsHandler($name . "Chunk Load - Entities", group: Timings::GROUP_BREAKDOWN); - $this->syncChunkLoadTileEntities = new TimingsHandler($name . "Chunk Load - TileEntities", group: Timings::GROUP_BREAKDOWN); - $this->syncChunkSave = new TimingsHandler($name . "Chunk Save", Timings::$worldSave, group: Timings::GROUP_BREAKDOWN); + $this->syncChunkLoad = self::newTimer($name, "Chunk Load"); + $this->syncChunkLoadData = self::newTimer($name, "Chunk Load - Data"); + $this->syncChunkLoadFixInvalidBlocks = self::newTimer($name, "Chunk Load - Fix Invalid Blocks"); + $this->syncChunkLoadEntities = self::newTimer($name, "Chunk Load - Entities"); + $this->syncChunkLoadTileEntities = self::newTimer($name, "Chunk Load - Block Entities"); - $this->doTick = new TimingsHandler($name . "World Tick"); + $this->syncDataSave = self::newTimer($name, "Data Save"); + $this->syncChunkSave = self::newTimer($name, "Chunk Save"); + + $this->chunkPopulationOrder = self::newTimer($name, "Chunk Population - Order"); + $this->chunkPopulationCompletion = self::newTimer($name, "Chunk Population - Completion"); } }