mirror of
https://github.com/pmmp/PocketMine-MP.git
synced 2025-10-16 11:58:00 +00:00
Implement send buffering and queuing for network sessions (#2358)
Async compression and broadcasts are now reliable and don't have race condition bugs. This features improved performance and significantly reduced bandwidth wastage. Reduce Level broadcast latency by ticking network after levels. This ensures that session buffers get flushed as soon as possible after level tick, if level broadcasts were done.
This commit is contained in:
@@ -71,7 +71,8 @@ use pocketmine\nbt\tag\LongTag;
|
||||
use pocketmine\nbt\tag\ShortTag;
|
||||
use pocketmine\nbt\tag\StringTag;
|
||||
use pocketmine\network\AdvancedNetworkInterface;
|
||||
use pocketmine\network\mcpe\CompressBatchedTask;
|
||||
use pocketmine\network\mcpe\CompressBatchPromise;
|
||||
use pocketmine\network\mcpe\CompressBatchTask;
|
||||
use pocketmine\network\mcpe\NetworkCipher;
|
||||
use pocketmine\network\mcpe\NetworkCompression;
|
||||
use pocketmine\network\mcpe\NetworkSession;
|
||||
@@ -1899,55 +1900,54 @@ class Server{
|
||||
$stream->putPacket($packet);
|
||||
}
|
||||
|
||||
//TODO: if under the compression threshold, add to session buffers instead of batching (first we need to implement buffering!)
|
||||
$this->batchPackets($targets, $stream);
|
||||
if(NetworkCompression::$THRESHOLD < 0 or strlen($stream->buffer) < NetworkCompression::$THRESHOLD){
|
||||
foreach($targets as $target){
|
||||
foreach($ev->getPackets() as $pk){
|
||||
$target->addToSendBuffer($pk);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$promise = $this->prepareBatch($stream);
|
||||
foreach($targets as $target){
|
||||
$target->queueCompressed($promise);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a list of packets in a batch to a list of players
|
||||
*
|
||||
* @param NetworkSession[] $targets
|
||||
* @param PacketStream $stream
|
||||
* @param bool $forceSync
|
||||
* @param bool $immediate
|
||||
* @param PacketStream $stream
|
||||
* @param bool $forceSync
|
||||
*
|
||||
* @return CompressBatchPromise
|
||||
*/
|
||||
public function batchPackets(array $targets, PacketStream $stream, bool $forceSync = false, bool $immediate = false){
|
||||
Timings::$playerNetworkSendCompressTimer->startTiming();
|
||||
public function prepareBatch(PacketStream $stream, bool $forceSync = false) : CompressBatchPromise{
|
||||
try{
|
||||
Timings::$playerNetworkSendCompressTimer->startTiming();
|
||||
|
||||
if(!empty($targets)){
|
||||
$compressionLevel = NetworkCompression::$LEVEL;
|
||||
if(NetworkCompression::$THRESHOLD < 0 or strlen($stream->buffer) < NetworkCompression::$THRESHOLD){
|
||||
$compressionLevel = 0; //Do not compress packets under the threshold
|
||||
$forceSync = true;
|
||||
}
|
||||
|
||||
if(!$forceSync and !$immediate and $this->networkCompressionAsync){
|
||||
$task = new CompressBatchedTask($stream, $targets, $compressionLevel);
|
||||
$promise = new CompressBatchPromise();
|
||||
if(!$forceSync and $this->networkCompressionAsync){
|
||||
$task = new CompressBatchTask($stream, $compressionLevel, $promise);
|
||||
$this->asyncPool->submitTask($task);
|
||||
}else{
|
||||
$this->broadcastPacketsCallback(NetworkCompression::compress($stream->buffer), $targets, $immediate);
|
||||
$promise->resolve(NetworkCompression::compress($stream->buffer));
|
||||
}
|
||||
}
|
||||
|
||||
Timings::$playerNetworkSendCompressTimer->stopTiming();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $payload
|
||||
* @param NetworkSession[] $sessions
|
||||
* @param bool $immediate
|
||||
*/
|
||||
public function broadcastPacketsCallback(string $payload, array $sessions, bool $immediate = false){
|
||||
/** @var NetworkSession $session */
|
||||
foreach($sessions as $session){
|
||||
if($session->isConnected()){
|
||||
$session->sendEncoded($payload, $immediate);
|
||||
}
|
||||
return $promise;
|
||||
}finally{
|
||||
Timings::$playerNetworkSendCompressTimer->stopTiming();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param int $type
|
||||
*/
|
||||
@@ -2542,10 +2542,6 @@ class Server{
|
||||
|
||||
++$this->tickCounter;
|
||||
|
||||
Timings::$connectionTimer->startTiming();
|
||||
$this->network->tick();
|
||||
Timings::$connectionTimer->stopTiming();
|
||||
|
||||
Timings::$schedulerTimer->startTiming();
|
||||
$this->pluginManager->tickSchedulers($this->tickCounter);
|
||||
Timings::$schedulerTimer->stopTiming();
|
||||
@@ -2556,6 +2552,10 @@ class Server{
|
||||
|
||||
$this->checkTickUpdates($this->tickCounter);
|
||||
|
||||
Timings::$connectionTimer->startTiming();
|
||||
$this->network->tick();
|
||||
Timings::$connectionTimer->stopTiming();
|
||||
|
||||
if(($this->tickCounter % 20) === 0){
|
||||
if($this->doTitleTick){
|
||||
$this->titleTick();
|
||||
|
Reference in New Issue
Block a user