Reputation: 1
I am developing a library that should work every minute. Sometimes this library doesn't wake at given time. It wakes after a delay. Example timestamps are like this:
12:00:00:250
12:01:00:250
12:02:00:249
12:03:15:350
12:04:39:751
First I was using Thread.sleep, after some researches I changed it to ScheduledExecutorService. I thought it should fix it. But same scenario is still happening.
Runnable runnable = new Runnable() {
@Override
public void run() {
//do something
}};
ScheduledExecutorService ses = Executors.newScheduledThreadPool(1);
ses.scheduleAtFixedRate(runnable, 0, 60 * 1000, TimeUnit.MILLISECONDS);
After some research I found it may be about deep sleep mode.(BTW main application that uses my library has wake-lock). I tried forcing to sleep mode:
adb shell dumpsys deviceidle force-idle
But it didnt happen in sleep mode. It may happen in random scenarios or I coulnd't found the real reason. Note: We are working on android 10 aosp device. It isn't a store application. What could I use to sleep in that precision? Or what could cause this problem?
Upvotes: 0
Views: 104
Reputation: 27190
Is there any mechanism to sleep exact 1 min precision?
No. You can have greater or lesser degrees of precision. For applications that need high precision, there are specialized real-time operating systems (RTOS), but even an RTOS can not give you exact timing. You need to put a number to your requirement (e.g., I need the routine to fire not more than so many microseconds late, not more than so many microseconds early, etc.) and then you need to choose hardware and software that can meet those requirements.
You're stuck with Android. I don't know what kind of guarantees Android can give you, and I don't know what hardware you're going to run it on, but...
...Is your requirement actually that the duration of each individual interval be precise? Or, would you be satisfied if your routine always was called at close to the correct wall-clock time on each iteration? That is to say, would you be satisfied if the routine always was called within so-many milliseconds of the same second in every minute:
12:00:00:250
12:01:00:017
12:02:00:183
12:02:59:920
.
.
.
18:00:00:061 #Look ma! Six hours later, and I haven't
18:01:00:298 # accumulated any error.
18:02:00:161
.
.
.
In other words, would you be satisfied if errors did not accumulate the way they were doing in your example?
I don't know why newScheduledThreadPool
allows the errors to accumulate, but I know how to write my own trivial scheduler that does not accumulate error.
import time
next_wakeup_time = time.time()
while True:
# do something
next_wakeup_time = next_wakeup_time + 60
time_now = time.time()
time_to_sleep = next_wakeup_time - time_now
time.sleep(time_to_sleep)
Each time around my loop, the next_wakeup_time
is incremented by exactly 60 seconds. I can't control precisely how long each time.sleep()
call will actually last, but I can eliminate the cumulative error by re-calculating time_to_sleep
in every iteration.
Each time my version //does something
, it may be off by a little, but over the long term, it will //do something
exactly 86,400 times per day, 604,800 times per week, and 31,536,000 times per (non-leap) year.
Upvotes: 1