Use Threading

Discussion in 'Plugin Development' started by Moon_werewolf, Sep 29, 2011.

Thread Status:
Not open for further replies.
  1. Offline

    Moon_werewolf

    I have a little problem. i have made a save format/system/function that compresses 500 000 block in 6 minutes to around 426kb the problem is it freezes my plugin until the compress timmer runs out. i don't like to use threading in a plugin but can i do it for his?

    the compression have all data it needs then it begins so it do not need to look up inventory in chests or blocks id and data, so how bad would it be to use something like this

    Code:
            while(hasTimeLeft())
            {
                for(NanoFamily f : NanoFamily.getAll())
                {
                    if(!f.isCompressing())
                    {
                        f.run();
                    }else{
                        new Thread(f).Start();
                    }
                }
            }
    the "compressor" are also using the function hasTimeLeft() so its stops after a the set time has pasted (default 250ms) then then it is done with its task i thinking of running System.gc(); just to clean up after it
     
  2. Offline

    rmb938

    use an async scheduler. while loops freeze and process unless its it another thread. bukkits scheduler fixes this problem
     
  3. Offline

    Moon_werewolf

    NanoFamily maybe needs to run more then once so then i create a NanoFamily is it a good idéa to use this scheduleAsyncRepeatingTask then stop it then it is done?

    Edit: coded little and made this codes, and i seams to work fine :)

    Code:
        public void start()
        {
            taskId = Bukkit.getScheduler().scheduleAsyncRepeatingTask(Nanobot.NanobotPlugin, this, 0, 20);
        }
    and later in the run code
    Code:
             if(o.getOrder() == NanoOrder.CANCEL)
            {
                if(taskId != -1){ Bukkit.getScheduler().cancelTask(taskId); }
                startLocation = null;
                remove();
                System.gc();
            }
     
  4. Offline

    Shamebot

    Using System.gc() isn't recommended.
     
  5. Bukkit calls System.gc() every freaking 20 ticks for some weird reason (really awesome idea imo ...[/sarcasm]). Just wanted to point that out ...


    On topic: I don't think you need a repeating task, since it's a single compressing operation that does not constantly redo its job.
    An async task and a spawned thread are essentially the same, so you might want to create an "async delayed task" and make your compressor run in that.
    But be aware of the rules when operating from another thread, more or less stated here: http://wiki.bukkit.org/Scheduler_Programming
     
  6. Offline

    Moon_werewolf

    din't know about the System.gc();

    ok Async to compress the file with out pauses? for now i have coded it is a way that supports pauses

    aslo my plugin nanobot uses also threads to "scan" block to edit then edits them then it's done. should that also be used with Async?

    for now i just have used some repeatingTask and made the plugin stops every 250ms so it don't freezes the server

    EDIT:
    I just tested, nanobot scanned and removed 1 000 000 block on 55 secounds with out any lag what so ever
     
  7. If you run your compression on the main server thread ("sync task") you would have to make it in intervals to let the server recover. You stated that it takes about 6 minutes, so that would be horrible on a public server to experience huge lags over such a time - unless you split it up in lots of tiny operations, which I also don't recommend.

    That's where another thread ("async task") comes in handy: You can do the whole thing in one period. As long as the CPU isn't 100% busy, it won't affect the server gameplay.
    If it's too CPU heavy you can even call Thread.sleep(...) sometimes to give the CPU a break.


    When you want to do block editing, you have to do it from the main server thread - because bukkit is not thread-safe, so the world could possibly corrupt at some point.
    But if searching the blocks takes most of the processing time, you could also do that in another thread, then just save information about the block changes and then apply them in a sync task.

    Most importantly: Whatever you prefer to do, never call bukkit methods from another thread, unless you know for 100% that they are thread-safe!
     
  8. Offline

    iffa

    ....and 99% of them are not.
     
  9. Offline

    Moon_werewolf

    So
    Compressing - Async
    Scanning - Async
    Editing - Sync

    It is like this. a player uses a editing command in my plugin then it a block that causes a object to be created and put in a ArrayList then the Tasks starts inside the object, can i have it that way?
     
  10. BTW:
    Are getServer(), getScheduler() and the methods from the scheduler thread safe? Yes, this is a serious question... :D
     
  11. Offline

    iffa

    Should be..?
     
  12. MMD... :D
     
  13. Offline

    Ahniolator

    Yes, they are. http://wiki.bukkit.org/Scheduler_Programming Look under "Thread-Safe API Methods"
     
    V10lator likes this.
  14. http://wiki.bukkit.org/Scheduler_Programming
    Look at the very bottom, there is a "list" of thread safe methods. The scheduler methods are safe, getServer() should be as well, since it will never change (Bukkit.getServer() simply returns a final field and has no setter, that means that field is thread safe if i recall correctly).
    getScheduler() should probably the same case, but I'm not sure there.

    If you want to play super safe, give your Runnable class the BukkitScheduler as a parameter when it's created, so you can access it from your other thread without getters ;)

    edit: too slow ;)
     
    V10lator likes this.
  15. Offline

    Moon_werewolf

    • The world.getBlockTypeIdAt(int x, int y, int z)
      • Note: It is just that one method, all the other block methods use the cache
    Do you know if that include .getLocation() and .getTypeId() from the block I'm getting?
     
  16. @Moon_werewolf
    world.getBlockTypeIdAt(int x, int y, int z)
    returns an id, not a Block ;)
    I don't know of a thread safe way to get the block data though. Might be possible with Spout (which also supports thread safe setting of blocks).
     
  17. Offline

    Moon_werewolf

    Hoo. didn't see that. well off to recode the scanning function
     
  18. Offline

    Shamebot

    Not anymore, AFAIK the commit has been reverted.
     
  19. *whew* good to know (just checked the source, it seems to be true, though nothing is listed in the changelog)
     
  20. Offline

    Afforess

    Grum force pushed, which overrode the master branch, and removed the commit from history. I guess he was displeased. :p
     
Thread Status:
Not open for further replies.

Share This Page