From 599c4284f560ce09aac1cda996743daf9d543aff Mon Sep 17 00:00:00 2001 From: "Dylan K. Taylor" Date: Tue, 16 May 2023 22:54:06 +0100 Subject: [PATCH] Introduce 10 KB threshold for async compression due to the extremely large performance cost of instantiating AsyncTasks, it's usually not worth bothering with async compression except for very large packets. While this large overhead can be significantly reduced by using specialized threads, it's early days in the testing stages for such improvements, and for now, we still have this to deal with. Since async compression is always used prior to player spawn, this change may slightly improve the performance of the pre-join stage of the game. --- resources/pocketmine.yml | 5 ++++- src/Server.php | 9 ++++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/resources/pocketmine.yml b/resources/pocketmine.yml index ac60afe53..408b5b95b 100644 --- a/resources/pocketmine.yml +++ b/resources/pocketmine.yml @@ -85,8 +85,11 @@ network: batch-threshold: 256 #Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage compression-level: 6 - #Use AsyncTasks for compression. Adds half/one tick delay, less CPU load on main thread + #Use AsyncTasks for compression during the main game session. Increases latency, but may reduce main thread load async-compression: false + #Threshold for async compression, in bytes. Only packets larger than this will be compressed asynchronously + #Due to large overhead of AsyncTask, async compression isn't worth it except for large packets + async-compression-threshold: 10000 #Experimental. Use UPnP to automatically port forward upnp-forwarding: false #Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be diff --git a/src/Server.php b/src/Server.php index a81b1d74b..11a2b157a 100644 --- a/src/Server.php +++ b/src/Server.php @@ -208,6 +208,8 @@ class Server{ private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND; private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND; + private const DEFAULT_ASYNC_COMPRESSION_THRESHOLD = 10_000; + private static ?Server $instance = null; private TimeTrackingSleeperHandler $tickSleeper; @@ -266,6 +268,7 @@ class Server{ private Network $network; private bool $networkCompressionAsync = true; + private int $networkCompressionAsyncThreshold = self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD; private Language $language; private bool $forceLanguage = false; @@ -908,6 +911,10 @@ class Server{ ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE)); $this->networkCompressionAsync = $this->configGroup->getPropertyBool("network.async-compression", true); + $this->networkCompressionAsyncThreshold = max( + $this->configGroup->getPropertyInt("network.async-compression-threshold", self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD), + $netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD + ); EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool("network.enable-encryption", true); @@ -1375,7 +1382,7 @@ class Server{ } $promise = new CompressBatchPromise(); - if(!$sync){ + if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){ $task = new CompressBatchTask($buffer, $promise, $compressor); $this->asyncPool->submitTask($task); }else{