Skip to content

Commit 6a25e66

Browse files
committed
could be buggy according to pr but wtv
1 parent 664a042 commit 6a25e66

File tree

7 files changed

+308
-87
lines changed

7 files changed

+308
-87
lines changed

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ Additions
4848
> https://github.com/pmmp/PocketMine-MP/pull/5581
4949
> https://github.com/pmmp/PocketMine-MP/pull/5583
5050
> https://github.com/pmmp/PocketMine-MP/pull/5800
51+
> https://github.com/pmmp/PocketMine-MP/pull/5805
5152
5253

5354
## What is this?

resources/pocketmine.yml

+4-5
Original file line numberDiff line numberDiff line change
@@ -85,11 +85,10 @@ network:
8585
batch-threshold: 256
8686
#Compression level used when sending batched packets. Higher = more CPU, less bandwidth usage
8787
compression-level: 6
88-
#Use AsyncTasks for compression during the main game session. Increases latency, but may reduce main thread load
89-
async-compression: false
90-
#Threshold for async compression, in bytes. Only packets larger than this will be compressed asynchronously
91-
#Due to large overhead of AsyncTask, async compression isn't worth it except for large packets
92-
async-compression-threshold: 10000
88+
#Max threads to use for packet compression. If disabled, compression will be done on the main thread.
89+
#Set to 0 to disable, or "auto" to try to detect the number of available CPU cores.
90+
#Higher values will allow using more CPU cores, but will also increase memory usage.
91+
compression-threads: auto
9392
#Experimental. Use UPnP to automatically port forward
9493
upnp-forwarding: false
9594
#Maximum size in bytes of packets sent over the network (default 1492 bytes). Packets larger than this will be

src/Server.php

+43-26
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
use pocketmine\network\mcpe\compression\CompressBatchPromise;
5353
use pocketmine\network\mcpe\compression\CompressBatchTask;
5454
use pocketmine\network\mcpe\compression\Compressor;
55+
use pocketmine\network\mcpe\compression\CompressorWorkerPool;
5556
use pocketmine\network\mcpe\compression\ZlibCompressor;
5657
use pocketmine\network\mcpe\convert\TypeConverter;
5758
use pocketmine\network\mcpe\encryption\EncryptionContext;
@@ -210,8 +211,6 @@ class Server{
210211
private const TICKS_PER_TPS_OVERLOAD_WARNING = 5 * self::TARGET_TICKS_PER_SECOND;
211212
private const TICKS_PER_STATS_REPORT = 300 * self::TARGET_TICKS_PER_SECOND;
212213

213-
private const DEFAULT_ASYNC_COMPRESSION_THRESHOLD = 10_000;
214-
215214
private static ?Server $instance = null;
216215

217216
private TimeTrackingSleeperHandler $tickSleeper;
@@ -269,8 +268,13 @@ class Server{
269268
private bool $onlineMode = true;
270269

271270
private Network $network;
272-
private bool $networkCompressionAsync = true;
273-
private int $networkCompressionAsyncThreshold = self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD;
271+
272+
private int $networkCompressionThreads;
273+
/**
274+
* @var CompressorWorkerPool[]
275+
* @phpstan-var array<int, CompressorWorkerPool>
276+
*/
277+
private array $networkCompressionThreadPools = [];
274278

275279
private Language $language;
276280
private bool $forceLanguage = false;
@@ -909,11 +913,13 @@ public function __construct(
909913
}
910914
ZlibCompressor::setInstance(new ZlibCompressor($netCompressionLevel, $netCompressionThreshold, ZlibCompressor::DEFAULT_MAX_DECOMPRESSION_SIZE));
911915

912-
$this->networkCompressionAsync = $this->configGroup->getPropertyBool(Yml::NETWORK_ASYNC_COMPRESSION, true);
913-
$this->networkCompressionAsyncThreshold = max(
914-
$this->configGroup->getPropertyInt(Yml::NETWORK_ASYNC_COMPRESSION_THRESHOLD, self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD),
915-
$netCompressionThreshold ?? self::DEFAULT_ASYNC_COMPRESSION_THRESHOLD
916-
);
916+
// todo maybe add toggle to use this or legacy network compression
917+
$netCompressionThreads = $this->configGroup->getPropertyString(Yml::NETWORK_COMPRESSION_THREADS, "auto");
918+
if($netCompressionThreads === "auto"){
919+
$this->networkCompressionThreads = max(1, Utils::getCoreCount() - 2);
920+
}else{
921+
$this->networkCompressionThreads = max(0, (int) $netCompressionThreads);
922+
}
917923

918924
EncryptionContext::$ENABLED = $this->configGroup->getPropertyBool(Yml::NETWORK_ENABLE_ENCRYPTION, true);
919925

@@ -1011,7 +1017,7 @@ public function __construct(
10111017

10121018
$this->queryInfo = new QueryInfo($this);
10131019

1014-
$playerDataProviderType = $this->configGroup->getPropertyString("player.default-data-format", "datfile");
1020+
$playerDataProviderType = $this->configGroup->getPropertyString(Yml::PLAYER_DEFAULT_DATA_FORMAT, "datfile");
10151021
$path = Path::join($this->dataPath, "players");
10161022
if ($playerDataProviderType === "datfile") {
10171023
$this->playerDataProvider = new DatFilePlayerDataProvider($path);
@@ -1364,6 +1370,17 @@ public function broadcastTitle(string $title, string $subtitle = "", int $fadeIn
13641370
return count($recipients);
13651371
}
13661372

1373+
private function getNetworkCompressionWorkerPool(Compressor $compressor) : CompressorWorkerPool{
1374+
$compressorId = spl_object_id($compressor);
1375+
$workerPool = $this->networkCompressionThreadPools[$compressorId] ?? null;
1376+
if ($workerPool === null) {
1377+
$this->logger->debug("Creating new worker pool for compressor " . get_class($compressor) . "#" . $compressorId);
1378+
$workerPool = $this->networkCompressionThreadPools[$compressorId] = new CompressorWorkerPool($this->networkCompressionThreads, $compressor, $this->tickSleeper);
1379+
}
1380+
1381+
return $workerPool;
1382+
}
1383+
13671384
/**
13681385
* @internal
13691386
* Promises to compress the given batch buffer using the selected compressor, optionally on a separate thread.
@@ -1382,26 +1399,22 @@ public function prepareBatch(string $buffer, Compressor $compressor, ?bool $sync
13821399
try{
13831400
$timings->startTiming();
13841401

1385-
$threshold = $compressor->getCompressionThreshold();
1386-
if($threshold === null || strlen($buffer) < $compressor->getCompressionThreshold()){
1387-
$compressionType = CompressionAlgorithm::NONE;
1388-
$compressed = $buffer;
1389-
1390-
}else{
1391-
$sync ??= !$this->networkCompressionAsync;
1402+
if($sync === null){
1403+
$threshold = $compressor->getCompressionThreshold();
1404+
$sync = $threshold === null || strlen($buffer) < $threshold;
1405+
}
13921406

1393-
if(!$sync && strlen($buffer) >= $this->networkCompressionAsyncThreshold){
1394-
$promise = new CompressBatchPromise();
1395-
$task = new CompressBatchTask($buffer, $promise, $compressor);
1396-
$this->asyncPool->submitTask($task);
1397-
return $promise;
1398-
}
1407+
if(!$sync && $this->networkCompressionThreads > 0){
1408+
$workerPool = $this->getNetworkCompressionWorkerPool($compressor);
13991409

1400-
$compressionType = $compressor->getNetworkId();
1401-
$compressed = $compressor->compress($buffer);
1410+
//TODO: we really want to be submitting all sessions' buffers in one go to maximize performance
1411+
$promise = $workerPool->submit($buffer);
1412+
}else{
1413+
$promise = new CompressBatchPromise();
1414+
$promise->resolve($compressor->compress($buffer));
14021415
}
14031416

1404-
return chr($compressionType) . $compressed;
1417+
return $promise;
14051418
}finally{
14061419
$timings->stopTiming();
14071420
}
@@ -1518,6 +1531,10 @@ public function forceShutdown() : void{
15181531
$this->network->unregisterInterface($interface);
15191532
}
15201533
}
1534+
foreach($this->networkCompressionThreadPools as $pool){
1535+
$this->logger->debug("Shutting down network compression thread pool for compressor " . get_class($pool->getCompressor()) . "#" . spl_object_id($pool->getCompressor()));
1536+
$pool->shutdown();
1537+
}
15211538
}catch(\Throwable $e){
15221539
$this->logger->logException($e);
15231540
$this->logger->emergency("Crashed while crashing, killing process");

src/YmlServerProperties.php

+2
Original file line numberDiff line numberDiff line change
@@ -94,12 +94,14 @@ private function __construct(){
9494
public const NETWORK_ASYNC_COMPRESSION_THRESHOLD = 'network.async-compression-threshold';
9595
public const NETWORK_BATCH_THRESHOLD = 'network.batch-threshold';
9696
public const NETWORK_COMPRESSION_LEVEL = 'network.compression-level';
97+
public const NETWORK_COMPRESSION_THREADS = 'network.compression-threads';
9798
public const NETWORK_ENABLE_ENCRYPTION = 'network.enable-encryption';
9899
public const NETWORK_MAX_MTU_SIZE = 'network.max-mtu-size';
99100
public const NETWORK_UPNP_FORWARDING = 'network.upnp-forwarding';
100101
public const PLAYER = 'player';
101102
public const PLAYER_SAVE_PLAYER_DATA = 'player.save-player-data';
102103
public const PLAYER_VERIFY_XUID = 'player.verify-xuid';
104+
public const PLAYER_DEFAULT_DATA_FORMAT = 'player.default-data-format';
103105
public const PLUGINS = 'plugins';
104106
public const PLUGINS_LEGACY_DATA_DIR = 'plugins.legacy-data-dir';
105107
public const SETTINGS = 'settings';

src/network/mcpe/compression/CompressBatchTask.php

-56
This file was deleted.

0 commit comments

Comments
 (0)