4

Let's say I want to make an event reminder in Python. It would read a file on startup containing a list of events (meetings, birthdays, etc), figure out which one is soonest, and then do something like time.sleep(1e7). Actually, that doesn't work: trying to sleep for ten million seconds gives an OverflowError. Okay, no problem: we'll call time.sleep(2**22) in a loop. It's a bit less elegant, but the overhead of waking up our process every 7 weeks for no good reason should have basically no impact on system performance or battery life or all those good things everyone likes when they warn us against calling sleep in a loop.

But! This doesn't work! It seems to work, unless you test what happens when you hibernate the computer. If you call time.sleep(60) and immediately hibernate, and then immediately power it back on, you will find that the time the computer spent turned off "doesn't count"; the program will wake up late, even if the whole hibernate/wake up thing took less than a minute. So, what to do about it? A common suggestion in this situation seems to be a busy loop: call sleep, and then when you wake up, check the time to see how much more sleep you can afford.

The problem with this approach is that it forces you to take very short naps or else be very unreliable. If the next event is several months away (maybe you just use the event reminder to keep track of birthdays), that doesn't mean we can afford to sleep for several weeks, because we don't know how much of that time the computer will be on. It could be that the computer will hibernate mere minutes after we call sleep, and remain off until the day before the event we should remind about. Thus, we could miss the event by several weeks, as well as whatever other events were shortly after it.

So, what's a safe time? One second is certainly safe; in fact, one second is probably overkill. Checking every ten seconds is probably safe; if someone put their computer to sleep and only turned it on less than ten seconds before their reminder is due, I don't think they can complain too much if it arrives a few seconds late. One minute is more dubious; for some things, being reminded a minute late makes little difference, for others it does. For instance, if your favorite TV show is at 4pm and your reminder is set to 3:59, then having it come a minute late is bad; the user had better know this can happen, and should set the reminder to 3:58 to compensate.

But the overhead of checking the time every minute is probably NOT negligible. At the very least, it discourages the OS from paging out the python interpreter and giving the memory to a more deserving process. Or if it does page it out, then the extra disk traffic generated every minute might slow down the game the user is trying to play, causing a glitch in the otherwise perfect 60 fps framerate.

Or maybe none of this would happen and I'm grossly overestimating the effects of calling sleep once in a while, but still feels wrong and kludgy and inelegant and inefficient and just plain icky. The operating system knows how long I've been sleeping; this job is trivial from its end. My program has no clue when the computer was hibernating, and it should not have to care. There should be some way to get the OS to use its knowledge to wake me at the right time. Am I right? Is there in fact such a way? And if so, what is it?

Mark VY
  • 1,489
  • 16
  • 31
  • 1
    Look at the source code to `cron`. It's authors tackled this problem decades ago. – Jonathon Reinhart Mar 28 '17 at 01:54
  • @JonathonReinhart I don't think `cron` handles this; that's why `anacron` exists. @TigerhawkT3: the answers on that page all seem to use a busy loop, unless I missed something. – Mark VY Mar 28 '17 at 05:18

0 Answers0