1. The forums will be archived and moved to a read only mode in about 2 weeks (mid march).

WHAT are some plugin development mistakes/bad practice that slows down a server?

Discussion in 'Development' started by Levi, Mar 11, 2019.

  1. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    WHAT are some plugin development mistakes/bad practice that slows down a server?
     
  2. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    PHP:
    sleep(1);
     
  3. jasonwynn10

    jasonwynn10 Moderator Poggit Reviewer

    Messages:
    1,489
    GitHub:
    jasonwynn10
    Packet send and receive events with no filter and player move events on large servers
    PHP:
    public function onDataPacketReceiveEvent(DataPacketReceiveEvent $event){

    }
    public function 
    onDataPacketSendEvent(DataPacketSendEvent $event){

    }
    public function 
    onPlayerMoveEvent(PlayerMoveEvent $event){

    }
     
    Muqsit likes this.
  4. Thunder33345

    Thunder33345 Moderator Staff Member

    Messages:
    2,137
    GitHub:
    Thunder33345
    fetching a website on main thread(but fetching on an async thread is a hack)
     
    jasonwynn10 likes this.
  5. Levi

    Levi Skeleton

    Messages:
    955
    GitHub:
    captainleviftw
    Then is there another way to make a border plugin without using PlayerMoveEvent to check if a player cross certain coordinates?
     
  6. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    Well listening to PlayerMoveEvent on large servers won't really cause any significant damage. The frequency of the event being called is high so limiting yourself to light code in such events would be great. F.e: Don't keep checking if a player is inside an octagon everytime PlayerMoveEvent is called. Maybe you can do a coordinate test to check whether the player moved a significant distance and only then proceed to check if point in octagon.

    I think empty events are fine, but not handling the event is always better. The event calling code is highly optimized and handle it or not, there's enough code already executed in attempting to call the event. PMMP has empty packet handlers for currently unhandled packets and it doesn't cause any significant performance drop. ¯\_(ツ)_/¯
     
  7. Muqsit

    Muqsit Chicken

    Messages:
    1,548
    GitHub:
    muqsit
    Appropriate event priorities + ignoreCancelled can save you some code execution. If I wrote a player region checker plugin that does something like this...
    PHP:
    /**
     * @param PlayerMoveEvent $event
     * @priority NORMAL
     * @ignoreCancelled true
     */
    public function onPlayerMove(PlayerMoveEvent $event) : void{
        
    // check if player moved inside an octagonal area.
    }
    Take an example of an anticheat plugin that listens to PlayerMoveEvent on a lower priority (i.e anticheat's listener gets executed before the region listener, eg: LOW, LOWEST). In this case, my region checker listener won't execute if your anticheat plugin cancels the event.
    Saved you a few code execution!
     
  8. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    This is oversimplification. Handling these events isn't evil; in fact, merely handling them has almost no impact on performance. It is only a problem when you start doing stupid stuff there.
     
    jasonwynn10 likes this.
  9. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    Not true. Can you possibly optimize anything in PHP (at the same time complexity)?
    Also see my analysis in https://forums.pmmp.io/threads/reas...ng-the-myths-of-its-performance-impacts.5603/
    Although that article might be slightly outdated, one thing isn't changed: It's just a few extra function calls, and as of PHP 7, the function call overhead is very small. What people usually think is that 4 or 5 function calls would have an impact on some event that involves dozens of other internal function calls.
    My personal principle is, unless your optimization involves more than 1ms execution, more than 50% performance improvement or different time complexities, it is a premature optimization.
    Just look at the other function calls in a single move event, then you'd see that a few extra function calls have no impact on the whole server.
    Please evaluate the proportion of events that are cancelled. Do you really think preventing these calls would make a significant difference? It's very likely that a PlayerMoveEvent or a DataPacketSendEvent is cancelled more than once per second on average.
    In addition, looking at the stack trace of an event, we have this:
    Code:
    [13:51:22] [Server thread/DEBUG]: #0 src/pocketmine/plugin/MethodEventExecutor(38): Foo->e(pocketmine\event\level\LevelLoadEvent object)                                                                         
    [13:51:22] [Server thread/DEBUG]: #1 src/pocketmine/plugin/RegisteredListener(98): pocketmine\plugin\MethodEventExecutor->execute(Foo object, pocketmine\event\level\LevelLoadEvent object)                       
    [13:51:22] [Server thread/DEBUG]: #2 src/pocketmine/event/Event(99): pocketmine\plugin\RegisteredListener->callEvent(pocketmine\event\level\LevelLoadEvent object)                                               
    [13:51:22] [Server thread/DEBUG]: #3 src/pocketmine/Server(1161): pocketmine\event\Event->call()                                          
    
    You actually only saved two calls from the 3 calls per handler. Two function calls have very very negligible effect on performance. Are you sure this makes any observable difference?

    Stop focusing on minor things like preventing a few function calls. Premature optimization is the root of all evil. Instead, try to understand every line of code you write and make sense of them.
    For example, if you run `new Config()` in PlayerMoveEvent, this will definitely lag the server, because you're opening a file stream every time, for hundreds of times per second. The problem is not from PlayerMoveEvent. The problem is from `new Config()`. I will equally think `new Config()` slows down your server even if it is in BlockBreakEvent or PlayerJoinEvent. (The problem is that you're using Config as a database; why not use libasynql?)
     
    HimbeersaftLP, jasonwynn10 and Muqsit like this.
  10. KielKing

    KielKing Zombie

    Messages:
    245
    GitHub:
    kielking
    great explanation, i'm not clear on the premature optimizations though, can you provide an example? nice plug at the end :D
     
  11. SOFe

    SOFe Administrator Staff Member PMMP Team Poggit Admin

    Messages:
    1,968
    GitHub:
    sof3
    If it's too complicated, let's think like this:
    • If it requires reading a file/Internet, try as hard as possible to make it async
    • If you are sure it could run more than 100000 loops (e.g. world editing), try to think of alternatives
    • It you suspect it slows down your server, test both versions a few times and see if there is obvious impact on TPS load. If you don't notice anything significant, don't try to optimize it.
    PHP itself is already slow. Trying to optimize other parts doesn't solve the bottleneck problem. Most of the time, plugins are just glue code, and they do not need very excellent optimization. (PMMP itself needs optimization because it has grown far too complex, but plugins, even big ones like EconomyAPI or FactionsPro, do not require optimization unless they do stupid stuff like reading files on the main thread)
     
    HimbeersaftLP and jasonwynn10 like this.
  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.