我有一个应用程序因为太多“线程唤醒”而崩溃。例如:
过去220秒内有45004次唤醒(平均每秒205次唤醒),超过300秒内每秒150次唤醒的限制
这很难调试,因为我不知道有什么直接的方法来测量线程唤醒。我找到的最接近的方法是一个称为“系统跟踪”的“仪器”模板,它会显示阻塞线程事件的数量。据推测,这是密切相关的,因为阻塞线程意味着该线程将休眠,然后在解除阻塞时唤醒。
奇怪的是,当应用程序正常运行并且没有崩溃时,阻塞线程的数量在每秒10,000个范围内。我的假设是,阻塞的、休眠的线程只在某些情况下计入“唤醒”限制--例如,我认为由于互斥锁而被锁定的线程也会计入。而在正常操作中简单地转换到其他线程的操作系统则不会。
如果Instruments有一个线程唤醒模板,我会很惊讶。我能找到的唯一文档在这里-https://developer.apple.com/library/content/technotes/tn2151/_index.html:
异常子类型WAKEUPS
表示进程中的线程每秒被唤醒太多次,这迫使CPU非常频繁地被唤醒并消耗电池寿命。
通常,这是由线程到线程的通信(通常使用peformSelector:onThread:
或dispatch_async
)导致的,这种通信在无意中发生的频率远远超过了它应该发生的频率。由于触发此异常的通信类型发生得如此频繁,因此通常会有多个后台线程具有非常相似的回溯跟踪-指示通信的起源。
3条答案
按热度按时间kwvwclae1#
下面是一些基于Ivan答案的Objective-C代码,您可以将其复制并粘贴到项目中的某个位置(例如,您的
applicationDidFinishLaunching:
方法),以记录每秒唤醒的次数(适用于Mac和iOS):cwxwcias2#
请看这里https://developer.apple.com/forums/thread/124180这里有一个在您的应用程序中获取唤醒计数的代码描述,而不仅仅是在仪器中。
此外,您还可以找到唤醒次数过多的一些原因。
sbdsn5lh3#
最后的“Energy Efficiency Guide for Mac Apps“提到了一个名为
timerfires
的命令行实用程序,可以用来查看是什么导致了唤醒。然而,该实用程序在macOS 12 Monterey上似乎已经过时了,因为当我第一次尝试运行它时,出现了如下错误:
探测器说明fbt::thread_dispatch:entry与任何探测器都不匹配
我必须复制该实用程序并对其进行编辑,以删除所有不再可用的DTrace方法,从而使该工具正常工作。
完成后,该工具将显示每个计时器调用,这对于跟踪计时器以减少唤醒非常有帮助。