StandardPacketBroadcaster: Improve performance when broadcasting small packets

In refactors during PM4, I stripped out packet buffer caching, as it was problematic when events alter packets in undetectable ways.
However, I never cleaned this part of the code up properly after enabling DataPacketSendEvent to include multiple packets and multiple targets, so we were still individually encoding the packet(s) for every single session if the sum total of the sizes was below 256 bytes.

This change encodes packets once in the StandardPacketBroadcaster and retains their buffers to post to the session's send buffer directly if the resulting batch is below compression threshold.
This code is still not optimal (see ##5589), but fixing this brings broadcasting performance back to PM3 levels, without any of PM3's problems.
This commit is contained in:
Dylan K. Taylor
2023-02-22 21:51:49 +00:00
parent 75bb4f8da6
commit 6a64486f55
2 changed files with 33 additions and 32 deletions

View File

@ -177,7 +177,7 @@ class NetworkSession{
private ?EncryptionContext $cipher = null;
/** @var ClientboundPacket[] */
/** @var string[] */
private array $sendBuffer = [];
/**
@ -264,23 +264,6 @@ class NetworkSession{
);
}
/**
* @param ClientboundPacket[] $packets
*/
public static function encodePacketBatchTimed(BinaryStream $stream, PacketSerializerContext $context, array $packets) : void{
PacketBatch::encodeRaw($stream, array_map(function(ClientboundPacket $packet) use ($context) : string{
$timings = Timings::getEncodeDataPacketTimings($packet);
$timings->startTiming();
try{
$stream = PacketSerializer::encoder($context);
$packet->encode($stream);
return $stream->getBuffer();
}finally{
$timings->stopTiming();
}
}, $packets));
}
private function onPlayerCreated(Player $player) : void{
if(!$this->isConnected()){
//the remote player might have disconnected before spawn terrain generation was finished
@ -498,7 +481,7 @@ class NetworkSession{
return false;
}
$this->addToSendBuffer($packet);
$this->addToSendBuffer(self::encodePacketTimed(PacketSerializer::encoder($this->packetSerializerContext), $packet));
if($immediate){
$this->flushSendBuffer(true);
}
@ -512,16 +495,24 @@ class NetworkSession{
/**
* @internal
*/
public function addToSendBuffer(ClientboundPacket $packet) : void{
$timings = Timings::getSendDataPacketTimings($packet);
public static function encodePacketTimed(PacketSerializer $serializer, ClientboundPacket $packet) : string{
$timings = Timings::getEncodeDataPacketTimings($packet);
$timings->startTiming();
try{
$this->sendBuffer[] = $packet;
$packet->encode($serializer);
return $serializer->getBuffer();
}finally{
$timings->stopTiming();
}
}
/**
* @internal
*/
public function addToSendBuffer(string $buffer) : void{
$this->sendBuffer[] = $buffer;
}
private function flushSendBuffer(bool $immediate = false) : void{
if(count($this->sendBuffer) > 0){
Timings::$playerNetworkSend->startTiming();
@ -534,7 +525,7 @@ class NetworkSession{
}
$stream = new BinaryStream();
self::encodePacketBatchTimed($stream, $this->packetSerializerContext, $this->sendBuffer);
PacketBatch::encodeRaw($stream, $this->sendBuffer);
if($this->enableCompression){
$promise = $this->server->prepareBatch(new PacketBatch($stream->getBuffer()), $this->compressor, $syncMode);