Akka scheduler tick duration to 1ms

In our application, we have the requirement to schedule functions with accuracy of milli seconds.

In order to achieve this, we were planning to use akka scheduler with following tick duration configuration.

akka.schedular.tick-duration = 1ms

What will be the challenges we might face and how much do you recommend keeping duration to 1ms?

@skvithalani and Shubham.

What garbage collector or JVM are you going to use? I think the biggest issue you will be facing is that as soon as you have a major GC, all your timing will be off when compared to an external system - so you should make sure to allocate everything at startup time (which might be somewhat tricky). Or you could use Azul’s Zing VM.

I don’t think you will get the desired precision by reducing the tick duration because the sleeping in the scheduler thread isn’t that exact. It will not trigger too early but later is possible.

I assume that your scheduled durations are not 1 ms. Then you can schedule something like 30 ms early and then use parkNanos, yield or spinning, in a loop until you hit the target. Measure with nanoTime.

But as mentioned, once you have gc pauses all bets are off.

Our project is going to be in production approx after 10 years and we plan to use latest JVM possible.

I think the conclusion is that even if we manage to pull the tick-duration at 1ms without having the GC getting triggered, the real question still remains that whether the scheduler will be precise enough to execute the function at exact ms time, and I think based on the Patrik’s reply it can be safely assumed that it cannot be said reliably that scheduler will work with ms precision.

Is that a fair conclusion?

If you have 10 years of time then perhaps by that time, there will be a completeley pause-free garbage collector as part of vanilla Java, which would be nice – but at this point it is speculation. Java 11’s ZGC certainly goes into that direction this being said, though I don’t know if that approach could one day lead to a 100% pause-free GC that would leave such timing threads entirely alone.

I think you can get a fair sub-millisecond measurement with the method described by Patrick - you won’t get a precision on the nanosecond level, but on the granularity of a ms you should be fine. You’d need to run this in a dedicated thread though.

It’s a bit hard to say more without knowing the context. I suppose another issue you might be facing is that even if the scheduler is perfectly precise, whether the execution of whatever is scheduled can happen at a latency that is acceptable (i.e. in less than a millisecond).

millisecond accuracy should be good enough for our requirement. To throw more light on the context, we might have more than one scheduling jobs in the same jvm with the frequency of let’s say 10 millis. So, if I have just one thread per jvm dedicated to do the scheduling job, are there any caveats that we need to consider?

With that being said, if I have more than one scheduling jobs in the same jvm all with 1 ms frequency than is it feasible to achieve ms accuracy with Patrik’s approach and again any caveats we need to consider?

And when it comes to whether the job scheduled for a particular frequency is itself completed by the time next tick for job happens is something we assume to be taken care of in our domain.

I don’t think you should have more than one thread doing the spinning to narrow in the exact time. That would be too wasteful. You can queue the tasks and then have a single thread dedicated for this. You can get some inspiration from our TaskRunner in Artery. https://github.com/akka/akka/blob/master/akka-remote/src/main/scala/akka/remote/artery/aeron/TaskRunner.scala