Uploaded image for project: 'Spigot'
  1. Spigot
  2. SPIGOT-7926

Update task scheduler

XMLWordPrintable

    • Icon: New Feature New Feature
    • Resolution: Unresolved
    • Icon: Minor Minor
    • None
    • None
    • 1.21+
    • Yes

      The current implementation of the task scheduler is quite good, but as I found it quite difficult to maintain and some of its solutions are redundant
      I propose to update the current implementation with some interesting changes:
      1) I dare say that a large number of tasks have the same period in ticks, e.g. 1 second - 20 ticks, 5 ticks, etc, quite popular periods. Each task can already act as a node for a linked list. In the mainThreadHeartbeat method, it is convenient to link identical periods because the priority queue is sorted when nodes are removed.
      This would probably lead to an optimization, since traversing related periods requires O( n ), where n is the number of tasks with the same period, instead of O(n(log( x )), where x is the total number of tasks. The logarithm is taken from binary heap considerations.

       queue |20| --> |50| --> |100| --> |120| periods
              ^|       ^|        ^|        ^|
              |v       |v        |v        |v
             +--+     +--+      +--+      +--+
             |t1|     |t3|      |t4|      |t6|
             +--+     +--+      +--+      +--+
              ^|       ^|                  ^|
              |v       |v                  |v
             +--+     +--+                +--+
             |t2|     |t5|                |t7|
             +--+     +--+                +--+
      
      

      2) Cancel task.
      At the moment, cancel a task looks a bit scary and probably not very efficient. For deleting, I would add another link to CraftTask - prev to effectively remove a particular node from the list of tasks in the same interval. But later I realized that adding to the map might reduce the efficiency of adding a task a bit. At the moment there is a linked list implementation that uses CAS, it's probably a good solution for a small concurrent case, which it is.

      Most tasks are aborted directly via BukkitTask itself, not via taskId, hence my solution: CraftTask is protected, so you can pass this task directly to the scheduler (via a method like cancel0(CraftTask task)).
      Well and the most important thing is to implement your binary heap with adding index to CraftTask, and change it at shifts within the queue, then any CraftTask can be obtained for O(1)

      Of the obvious solutions for an asynchronous scheduler is a new vorker that will work with its local queue. Such a solution is quite simple to implement. At the same time it can reduce contention even more. Well, it is clear that cachedthreadpool creates threads, and it costs something, and it is not very good to do it in the main thread of the server. + This would reduce the time complexity for PriorityQueue.

      P.S Although I don't understand who needs async tasks tied to ticks, they are not guaranteed to be executed on ticks anyway, of course CachedThreadPool will try to make sure everyone has time, but at the great cost of OS threads

      Demo Ver: https://github.com/sunmisc/wormhole/blob/main/main/src/main/java/sunmisc/utils/concurrent/sched/CraftScheduler.java

            Unassigned Unassigned
            JolyJDIA Sunmisc
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated: