Avoid unnecessary events work in handleDataPacket if the events have no registered handlers

this particular optimisation became possible thanks to changes in 4.19.

I observed that the allocation of Event objects and calling ->call() was costing us a significant percentage of the time taken in PlayerAuthInputPacket handlers. This change produces a measurable 2 microsecond reduction in overhead for PlayerAuthInputPacket handling when players are not moving (10.7 -> 8.7 microseconds). On a server with 200 players, this translates into a 1% reduction in CPU load for PlayerAuthInputPacket alone. It will also benefit other packets, but not to the extent that PlayerAuthInputPacket benefits.
This commit is contained in:
Dylan K. Taylor 2023-04-16 20:51:55 +01:00
parent 84cb070d56
commit 0629d11e13
No known key found for this signature in database
GPG Key ID: 8927471A91CAFD3D
2 changed files with 31 additions and 15 deletions

View File

@ -27,6 +27,7 @@ declare(strict_types=1);
namespace pocketmine\event; namespace pocketmine\event;
use pocketmine\timings\Timings; use pocketmine\timings\Timings;
use function count;
use function get_class; use function get_class;
abstract class Event{ abstract class Event{
@ -67,4 +68,14 @@ abstract class Event{
$timings->stopTiming(); $timings->stopTiming();
} }
} }
/**
* Returns whether the current class context has any registered global handlers.
* This can be used in hot code paths to avoid unnecessary event object creation.
*
* Usage: SomeEventClass::hasHandlers()
*/
public static function hasHandlers() : bool{
return count(HandlerListManager::global()->getListFor(static::class)->getListenerList()) > 0;
}
} }

View File

@ -401,11 +401,13 @@ class NetworkSession{
$timings->startTiming(); $timings->startTiming();
try{ try{
if(DataPacketDecodeEvent::hasHandlers()){
$ev = new DataPacketDecodeEvent($this, $packet->pid(), $buffer); $ev = new DataPacketDecodeEvent($this, $packet->pid(), $buffer);
$ev->call(); $ev->call();
if($ev->isCancelled()){ if($ev->isCancelled()){
return; return;
} }
}
$decodeTimings = Timings::getDecodeDataPacketTimings($packet); $decodeTimings = Timings::getDecodeDataPacketTimings($packet);
$decodeTimings->startTiming(); $decodeTimings->startTiming();
@ -424,9 +426,13 @@ class NetworkSession{
$decodeTimings->stopTiming(); $decodeTimings->stopTiming();
} }
if(DataPacketReceiveEvent::hasHandlers()){
$ev = new DataPacketReceiveEvent($this, $packet); $ev = new DataPacketReceiveEvent($this, $packet);
$ev->call(); $ev->call();
if(!$ev->isCancelled()){ if($ev->isCancelled()){
return;
}
}
$handlerTimings = Timings::getHandleDataPacketTimings($packet); $handlerTimings = Timings::getHandleDataPacketTimings($packet);
$handlerTimings->startTiming(); $handlerTimings->startTiming();
try{ try{
@ -436,7 +442,6 @@ class NetworkSession{
}finally{ }finally{
$handlerTimings->stopTiming(); $handlerTimings->stopTiming();
} }
}
}finally{ }finally{
$timings->stopTiming(); $timings->stopTiming();
} }