1.15.2 Multi-Tick Synchronous Tasks

Discussion in 'Spigot Plugin Development' started by CrypticCabub, Jan 25, 2020.

  1. I am well aware of multi-threading principles and techniques. What I am looking to do (and have already done -- this is a theoretical upgrade to code that already exists and has been working for some time) is get some sort of scheduler that is able to allocate execution times to various tasks on the main server thread while ensuring that those tasks do not cause lag on the main server thread by exceeding the 50ms/tick limit. I already have design ideas for dynamic profiling and aging of task execution time so that the scheduler can reasonably predict how much time a given task will take for its next chunk of execution, but my question/problem is in getting my code into a place where it can be one of the last things executed on a given tick and can in some way know how much time is remaining in that tick.
     
  2. Obtaining the snapshot must be done sync. It can then be used safely async.

    I’m echoing many of the points Warren made previously, but hopefully I’ll be able to elaborate more precisely why what you’ve suggested is misleading/incorrect.

    Calling methods in an async task means that the method is executed in that async context. If every method you called in the Bukkit API offloaded it work to the main thread, you’d end up with extra logic in every method either to check the current thread and/or to offload the task to another thread. Since the API explicitly states that it is not thread-safe, it wouldn’t make sense to implement this when every plugin is expected to conform to the thread safety policies of the API. Otherwise, everyone takes a hit in performance.

    No, the function called does the work in the same context. See above.

    Reading or writing corrupt or incorrect data will not throw any exceptions (if it did, everyone’s multithreaded code would do it!). In other words, the absence of an exception isn’t proof that your code is safe.

    See above

    As far as I am aware, changing a block requires multiple changes to different states. Inconsistencies from the lack of atomicity and racy reads (and writes) with the main thread means everyone loses. If anything, you don’t want the main thread to be taking the fall because the vast majority plugins behave correctly because they use the main thread.

    Offloading work to another thread in itself has a performance penalty so the perceived gain in performance remains to be seen through real world testing, not speculation.

    Depends on when the scheduler is executed in relation to things like doing actual server processing (ticking entities, worlds etc),calling events and dispatching commands. It may be worthwhile looking for usages of CraftScheduler#mainThreadHeartbeat() (been a while, might not be that signature specifically) and seeing where it’s called. I don’t expect it to be the last thing executed so if you want to have a task run at the end of the tick you’ll have to either find a different proxy to insert your task or even modify the server jar itself.
     
    • Agree Agree x 1
    • Informative Informative x 1
  3. Thanks! It looks like another higher-priority project may end up taking all of my time for the next few weeks but if I do find the time perhaps I'll try and clone into the Spigot repo and see if its possible to expand upon the scheduler already within Spigot. Even if it's not the absolute last thing run, being able to run after all the base game processing and perhaps between high-priority and monitor-priority tasks would be sufficient to get the desired outcome from the scheduler. Any idea as to if such a scheduler 'upgrade' would be something MD5 would want as part of the core Spigot API?
     
  4. Open an enhancement issue on JIRA, no one on the forums can tell you exactly unless md5 comes or something.