onMove Performance

Discussion in 'Plugin Development' started by RoGER.ONeill, Jun 2, 2011.

Thread Status:
Not open for further replies.
  1. Hi,

    I am currently interested in the onPlayerMove Listener.
    Does anyone know if it has a huge Performance impact,
    using it on the highest Priority?

    And what can I possibly do to reduce the Performance impact.
    (Cheap Operations to reduce Heap)

    I thought about adding that:
    Code:
    if (System.currentMillis-Long.valueOf(lastMillis.get(event.getPlayer().getName))>2000)
    {
        // DO STUFF
    }
    
    But I am not quite sure if it isn't actually causing more Heap, than
    just to leave it away.

    Edit: And please don't tell me, there is another Thread explaining that, exactly below mine... :p
     
  2. Offline

    Intelli

    If you're just tracking x/z movement, this is what I do:

    Code:
    @Override
    public void onPlayerMove(PlayerMoveEvent event){
    Player current = event.getPlayer();
    Location from = event.getFrom();
    int fromx = (int)from.getX();
    int fromz = (int)from.getZ();
    int x1 = (int)current.getLocation().getX();
    int z1 = (int)current.getLocation().getZ();
    
    if (x1!=fromx || z1 != fromz){
    //do stuff here
    }
    }
    
    This makes it so my heavier code is only run when a player has actually moved from one block to the next. This also makes it so jumping, etc, is ignored.

    Otherwise, if you have it send you a message whenever the onplayermove is ran (for testing), you'll see that it's doing hundreds of checks, for not very much movement.
     
  3. Yeah thats what I thought. Your Code seems fairly efficient, but you could use event.getTo insteading of getting the Player first. Dont know if that would make a difference though.
     
  4. Offline

    DreadKyller

    you could use getFrom() instead of getting the player, because until the end of the script the player does not move, and therefore getFrom is the same thing as getPlayer().getLocation() because they both lead to the same point.
     
  5. Offline

    Shamebot

    The priority of the Listener has nothing to do with the performance, it simply determines in which order the listeners are called.
     
  6. Offline

    Dreadreaver

    As the Move event is called like a brazillion times when you have some players moving around and because it's all on the same thread it is very very bad if you do too many checks. Try to exit the onMove as soon as possible! If you do too many calculations it'll slow down your whole server.
    Also if your code does not necessarily has to be ran 100% sync to Minecraft(if you only want to log something for example) you can just do it like this:
    Code:
    onMoveEvent(){
     if(player.XXX == what I want){
      plugin.process();
     }
    }
    where plugin is the class with onEnable and process() could just process the whole calculation in a seperate thread ... but make sure its an async thread as a sync thread wouldn't help that much :p
    Anyway it's always good to exit the onEvents as soon as possible!

    100% true. Use priorities to make your plugin work with other plugins. For example I use the lowest priority on BedRespawn so that other plugins can take over if they want and if no other plugin messes around with the respawn BedRespawn will just perform as planned.
     
  7. Offline

    DreadKyller

    @Dreadreaver / @Shamebot : Very good point to make. @RoGER.ONeill you know how you can cancel the events? well even after being canceled it still goes through every other plugin and listener registered. The reason is to check if another plugin needs to modify or uncancel it. The reason there is priorities is because High priority can not be undone of canceling by an event register for Normal, Highest can only be overwriten by Monitor, which is not a good choice to use that for canceling events and such, monitor should be mainly used to check if the event is already being canceled from the plugins called before it. imagine it sort of like this, of coarse it's no where near ( I think) to how they do it:

    PHP:
    for(Listener Priorities.Lowest){
        
    Listener.run();
    }
    for(
    Listener Priorities.Low){
        
    Listener.run();
    }
    for(
    Listener Priorities.Normal){
        
    Listener.run();
    }
    for(
    Listener Priorities.High){
        
    Listener.run();
    }
    for(
    Listener Priorities.Highest){
        
    Listener.run();
    }
    for(
    Listener Priorities.Monitor){
        
    Listener.run();
    }
    once again, that's not how they do it, but that would probably work if there was such a thing as the run method for a listener... But anyways, I wrote that mainly to give a perspective of what priorities do, highest come last so nothing can override its changes except higher or the same priority (I think the same priority can at least...)
     
  8. Offline

    GardenGnomer

    I'm very interested in this for generating trigger areas, but I know too little Java to work with async. Could someone please post some demo code I can steal from?
     
  9. Offline

    fullwall

    @GardenGnomer - create a class extending thread, and start the thread during onPlayerMove. Make sure that the thread will eventually stop itself, to avoid memory leaks.
     
  10. Offline

    Dreadreaver

    @fullwall
    I'd rather suggest creating a class implementing Runnable and then you use the bukkit scheduler!
     
  11. Offline

    fullwall

    That's not threaded.
     
  12. Offline

    Dreadreaver

    If I create an async thread using the BukkiScheduler it's obviously threaded.
     
  13. Offline

    matejdro

    What stuff can be done from another thread? I'm doing a lot of checks in that event, but most of the things evolves around bukkit stuff like player location or block types. I read on bukkit scheduler page that i should not use anything but world.getBlockTypeIdAt(int x, int y, int z) , which means that I'm stuck at one thread.
     
  14. Offline

    maystorm

    Is there any alternative to using "onPlayerMove" if one is only interested in receiving an event when the player changed block positions?
     
  15. Offline

    Evenprime

    No.

    But people overestimate the cost for handling onPlayerMove events anyway. The server does already a ton of calculations for every move event (e.g. checking if the new player position intersects with the hitbox of any of the other entities/players/enemies/blocks on the server), so doing some calculations in addition really won't slow down the server. I also strongly recommend to not spawn seperate threads/async tasks inside playerMove events. The overhead will almost always be gigantic compared to just doing whatever you want to do directly in there.

    For reference, this whole code blob gets executed for every PlayerMove event in my plugin: https://github.com/Evenprime/NoChea...me/bukkit/nocheat/checks/MovingCheck.java#L92 and its full execution takes less than 40 micro seconds. Just creating a new thread takes already up to 5ms (5000 micro seconds) and then it hasn't done anything yet. Registering async tasks with bukkit and getting them executed will likely have a similar impact.

    If you want a simple way to measure the time it takes to execute your onPlayerMove event, just use:

    Code:
    long startTime = System.nanoTime();
    
    // your event handling code
    
    long endTime = System.nanoTime() - startTime;
    
    System.out.println((endTime/1000) + " micro seconds");
    
    You'll probably be surprised how fast it is. Another tip: when measuring the time, remove all System.out.println() and other debug stuff first from your code - or your results will be wrong. A simple System.out.println() will take a real long time (for me it takes ~ 1 ms), that's more than 10 times what the actual code needs for execution.
     
  16. Offline

    maystorm

    Great explanation, thx!
     
Thread Status:
Not open for further replies.

Share This Page