From ab21fcdd675697d73d274eea14419641c8ae34f0 Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 16 Jan 2023 19:26:32 +0000 Subject: [PATCH 1/3] Server: fixed load statistics not including Snooze processing time this has been a bug ever since Snooze was first introduced. The load statistic, similarly to timings, did not account for time spent processing notifications between ticks. The problem is that this is often where a significant amoutn of the load actually comes from, because Snooze is most often activated due to incoming packets. This change fixes the problem by including the time spent processing notifications since the previous tick in the current tick's usage metric. --- src/Server.php | 12 ++++++----- ...ler.php => TimeTrackingSleeperHandler.php} | 21 +++++++++++++++++-- 2 files changed, 26 insertions(+), 7 deletions(-) rename src/{timings/TimingsAwareSleeperHandler.php => TimeTrackingSleeperHandler.php} (62%) diff --git a/src/Server.php b/src/Server.php index b20ec0a35b..ddc1bb07de 100644 --- a/src/Server.php +++ b/src/Server.php @@ -90,7 +90,7 @@ use pocketmine\scheduler\AsyncPool; use pocketmine\snooze\SleeperHandler; use pocketmine\stats\SendUsageTask; use pocketmine\timings\Timings; -use pocketmine\timings\TimingsAwareSleeperHandler; +use pocketmine\TimeTrackingSleeperHandler; use pocketmine\timings\TimingsHandler; use pocketmine\updater\UpdateChecker; use pocketmine\utils\AssumptionFailedError; @@ -187,7 +187,7 @@ class Server{ private static ?Server $instance = null; - private SleeperHandler $tickSleeper; + private TimeTrackingSleeperHandler $tickSleeper; private BanList $banByName; @@ -783,7 +783,7 @@ class Server{ $this->startTime = microtime(true); Timings::init(); - $this->tickSleeper = new TimingsAwareSleeperHandler(Timings::$serverInterrupts); + $this->tickSleeper = new TimeTrackingSleeperHandler(Timings::$serverInterrupts); $this->signalHandler = new SignalHandler(function() : void{ $this->logger->info("Received signal interrupt, stopping the server"); @@ -1866,14 +1866,16 @@ class Server{ Timings::$serverTick->stopTiming(); $now = microtime(true); - $this->currentTPS = min(20, 1 / max(0.001, $now - $tickTime)); - $this->currentUse = min(1, ($now - $tickTime) / 0.05); + $totalTickTimeSeconds = $now - $tickTime + ($this->tickSleeper->getNotificationProcessingTime() / 1_000_000_000); + $this->currentTPS = min(20, 1 / max(0.001, $totalTickTimeSeconds)); + $this->currentUse = min(1, $totalTickTimeSeconds / 0.05); TimingsHandler::tick($this->currentTPS <= $this->profilingTickRate); $idx = $this->tickCounter % 20; $this->tickAverage[$idx] = $this->currentTPS; $this->useAverage[$idx] = $this->currentUse; + $this->tickSleeper->resetNotificationProcessingTime(); if(($this->nextTick - $tickTime) < -1){ $this->nextTick = $tickTime; diff --git a/src/timings/TimingsAwareSleeperHandler.php b/src/TimeTrackingSleeperHandler.php similarity index 62% rename from src/timings/TimingsAwareSleeperHandler.php rename to src/TimeTrackingSleeperHandler.php index 80a1a0c576..970d85ce08 100644 --- a/src/timings/TimingsAwareSleeperHandler.php +++ b/src/TimeTrackingSleeperHandler.php @@ -21,14 +21,19 @@ declare(strict_types=1); -namespace pocketmine\timings; +namespace pocketmine; use pocketmine\snooze\SleeperHandler; +use pocketmine\timings\TimingsHandler; +use function hrtime; /** * Custom Snooze sleeper handler which captures notification processing time. + * @internal */ -final class TimingsAwareSleeperHandler extends SleeperHandler{ +final class TimeTrackingSleeperHandler extends SleeperHandler{ + + private int $notificationProcessingTimeNs = 0; public function __construct( private TimingsHandler $timings @@ -36,11 +41,23 @@ final class TimingsAwareSleeperHandler extends SleeperHandler{ parent::__construct(); } + /** + * Returns the time in nanoseconds spent processing notifications since the last reset. + */ + public function getNotificationProcessingTime() : int{ return $this->notificationProcessingTimeNs; } + + /** + * Resets the notification processing time tracker to zero. + */ + public function resetNotificationProcessingTime() : void{ $this->notificationProcessingTimeNs = 0; } + public function processNotifications() : void{ + $startTime = hrtime(true); $this->timings->startTiming(); try{ parent::processNotifications(); }finally{ + $this->notificationProcessingTimeNs += hrtime(true) - $startTime; $this->timings->stopTiming(); } } From 0bb9fb09cc3730c38969d451200c99da3801632e Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 16 Jan 2023 19:39:24 +0000 Subject: [PATCH 2/3] CS again --- src/Server.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Server.php b/src/Server.php index ddc1bb07de..04d8e04060 100644 --- a/src/Server.php +++ b/src/Server.php @@ -90,7 +90,6 @@ use pocketmine\scheduler\AsyncPool; use pocketmine\snooze\SleeperHandler; use pocketmine\stats\SendUsageTask; use pocketmine\timings\Timings; -use pocketmine\TimeTrackingSleeperHandler; use pocketmine\timings\TimingsHandler; use pocketmine\updater\UpdateChecker; use pocketmine\utils\AssumptionFailedError; From 6c0254c1eb5001fd833d68b63bb84f7bd541db1a Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Mon, 16 Jan 2023 19:49:24 +0000 Subject: [PATCH 3/3] Block: document parameters of place() --- src/block/Block.php | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/block/Block.php b/src/block/Block.php index 2e6dcb4ef4..625509be40 100644 --- a/src/block/Block.php +++ b/src/block/Block.php @@ -253,6 +253,14 @@ class Block{ * Generates a block transaction to set all blocks affected by placing this block. Usually this is just the block * itself, but may be multiple blocks in some cases (such as doors). * + * @param BlockTransaction $tx Blocks to be set should be added to this transaction (do not modify thr world directly) + * @param Item $item Item used to place the block + * @param Block $blockReplace Block expected to be replaced + * @param Block $blockClicked Block that was clicked using the item + * @param int $face Face of the clicked block which was clicked + * @param Vector3 $clickVector Exact position inside the clicked block where the click occurred, relative to the block's position + * @param Player|null $player Player who placed the block, or null if it was not a player + * * @return bool whether the placement should go ahead */ public function place(BlockTransaction $tx, Item $item, Block $blockReplace, Block $blockClicked, int $face, Vector3 $clickVector, ?Player $player = null) : bool{