Simplified integrated WSTP timer #3101
Replies: 4 comments 8 replies
-
Thanks for starting this discussion Tim. You're right, work on this has somewhat fizzled out, because there's one issue that we haven't found a good solution for. What you described has already been implemented once, but we didnt go through with it all the way because of the possibility of some sleeping fibers to lag behind a CPU intensive task. Imagine that a fiber sleeps, and as you said, it gets put on the thread local heap. Then that same thread goes on to execute a long CPU intensive task, pushing way past the wakeup time of the sleeping fiber. We haven't yet thought of a way for another free thread to steal the sleeping fiber and wake it up on time. Or rather, we don't yet have a good concurrent heap implementation that would allow us to do that. Daniel has some ideas, but maybe the best thing to do would be to find a white paper/research paper/library and essentially reimplement that. Our usual source of inspiration, JCTools is also lacking in this department. |
Beta Was this translation helpful? Give feedback.
-
It's worth noting that long CPU intensive tasks are an anti-pattern for Cats Effect (hence ideas like the starvation detector in #3090). That doesn't mean it's unrealistic in practice of course. But it seems to complicate the implementation exponentially ... and even more so if we get into the integrated I/O runtime idea and have to start thinking about stealing I/O events. See discussion in Discord where Daniel seems to think it's okay to not have timer stealing.
💯 to this. At least, starting with a non-stealing version and maybe making it opt-in we could get folks trying it out and find out how important stealing is or isn't. Coupled with Tim's starvation detector we might actually be able to collect decent empirical data on this.
Do we really need this? Seems like a waste of a thread, why not make it an externally-scheduled sleep on the WSTP (just like an externally queued task). |
Beta Was this translation helpful? Give feedback.
-
This is a very good idea!! If people believe that their app doesn't have long cpu intensive tasks then they can try it out and hopefully get a much better timer and give us some feedback! As you say, monlithic cpu intensive tasks are an anti-pattern anway so I could even live with us supporting both options and potentially flipping the default at some point in the future (but hopefully we'll have worked the stealing version out by then anyway)
Maybe not! I thought that we still needed to keep the existing scheduled executor for bincompat anyway and just suggested it as an easy way to support a relative edgecase. Probably we can do better! |
Beta Was this translation helpful? Give feedback.
-
I've done a brief survey of the literature and from what I can see, the state of the art seems to be a variant of a concurrent skip list. Those implementations all exploit marking pointers and various low-level things which are probably nasty to do on the JVM, but might be achievable with However these are all solving a more general problem than we have. AFAICT all we need is to integrate a hashed wheel timer into the WSTP. There is some prior art here as well which uses combining funnels. They are still solving a more general problem however - we want to do batch reads on a bucket so our read contention should be very low (or none if we maintain an TLDR: my proposal is that we build our own hashed wheel timer, that would basically be Pseudocode (don't read anything into the details 😅):
|
Beta Was this translation helpful? Give feedback.
-
Please do tell me if I've just completely missed the point but it seems to me that work on a more performant timer has somewhat stalled and/or been rolled into the integrated runtime discussion. While this is super exciting, it feels like there's more design work to do there which might take quite a while. In the meantime, it seems to me that a first version of a timer should be relatively straightforward, super valuable and compatible with future runtime work.
My current understanding is that we could do the following:
sleep
when running on a thread other than the WSTP (done via aThread.currentThread().isInstanceOf
just like we do for scheduling currently)n
iterations we dequeue fibers whose wait time has elapsed and add them to the queue of runnable fibersFrom my understanding, this would have the following advantages over the current scheduled executor service design:
sleep
currently actually blocks on the WSTP trying to acquire a lock to enqueue on the scheduled executor service)Time for everyone to pile on. What have I missed? 😅
Beta Was this translation helpful? Give feedback.
All reactions