qwerty
qwerty

Reputation: 1

Is there any mechanism to sleep exact 1 min precision?

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

Answers (2)

Solomon Slow
Solomon Slow

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

Phantom Lord
Phantom Lord

Reputation: 701

Try with AlarmManager.setAlarmClock

Upvotes: -1

Related Questions