检测系统在循环中挂起
Posted
技术标签:
【中文标题】检测系统在循环中挂起【英文标题】:Detecting system suspend in a loop 【发布时间】:2018-06-10 16:07:04 【问题描述】:我正在尝试使用以下算法检测系统挂起:
while True:
lastchecked = now()
if now() - lastchecked > 1s: print "suspend detected!"
但是我遇到了一个问题:如果挂起发生在第 2 行和第 3 行之间,那么循环会捕获它。但是如果挂起发生在第一行和第二行之间,那么算法就会失败。
这种情况有什么常用的方法吗?最好是独立于操作系统的,我不想挂钩操作系统事件等。
【问题讨论】:
看起来像XY problem。请添加您想要达到的目标的详细信息 - 一定有比投票更好的方法。 在绝大多数情况下,您不需要检查系统是否挂起——一个设计良好的算法会简单地从它停止的地方继续。这就是系统挂起的全部目的。 我的程序是一种系统监视器类型的应用程序——它需要知道系统是否进入休眠状态以及休眠了多长时间。 【参考方案1】:首先,polling is inferiour to notifications 因为它浪费了系统资源,而这些资源本来可以花在有用的工作上(你当前的循环也是busy loop)。当然,电源管理事件系统是特定于操作系统的(请参阅Power Management Notifications in Linux 和 how to hook to events / messages in windows using python),但如果您正在编写系统监视器应用程序,无论如何您都无法隐藏操作系统差异。
现在,这里的关键是在内存中总是有两个时间戳并覆盖旧的:
T1
\
T2
<- compare
/
T3
<- compare
\
T4
etc
/
然后,无论何时发生挂起,下一个时间戳都会设置得比它应该设置的晚,并且比较会看到差异。
这样,您甚至不需要每秒钟左右轮询一次!您的轮询间隔只需与您想要检测的最短暂停时间一样短。例如。如果您想检测至少 30 秒的暂停时间,您只需每 30 秒轮询一次:如果系统睡眠时间更长,则可以保证“错过一个节拍”。
i=0
poll_period=30
t=[time.time()]*2
while True:
# actually, poll period will be slightly longer due to code overhead:
# https://***.com/questions/26774186/looping-at-a-constant-rate-with-high-precision-for-signal-sampling
# but that doesn't make a difference in this case
time.sleep(poll_period)
t[i]=time.time()
if t[i] - t[(i+1)%2] > poll_period + 2: print "suspend detected"
i = (i+1)%2
请注意you will get false positives if your process gets preempted by others。这也是为什么使用系统通知是一种非常优越的方式的另一个原因。
【讨论】:
如果我想在循环中加入更多的函数调用,放在哪里重要吗? @user2108462 不是真的,但如果它们都在time.sleep()
的同一侧,那可能会更容易——那么您将确定哪个代码的开销是哪个测量间隔的一部分。 【参考方案2】:
我认为这个算法有效:
last1 = now()
last2 = now()
while True:
last1 = now()
if now() - last1 > 1s or now() - last2 > 1s: print "suspend detected!"
last2 = now()
if now() - last1 > 1s or now() - last2 > 1s: print "suspend detected!"
这将在 while 循环中的任何行之后立即检测到暂停:
第一行之后的挂起将被第二行检测到(因为 last1 将是旧的)。 第 4 行将检测到第二行之后的挂起(因为 last1 将是旧的)。 第 3 行之后的挂起将被第 4 行检测到(因为 last1 和 last2 都将是旧的)。 第 4 行之后的挂起将被第 2 行检测到(因为 last2 将是旧的)。我相信这是检测系统挂起所需的最少代码量。如果我错了,请纠正我。
【讨论】:
仍然是一个繁忙的循环以上是关于检测系统在循环中挂起的主要内容,如果未能解决你的问题,请参考以下文章
UIViewController 在 Xcode 7 中挂起