iOS - 如何测量线程唤醒?

Posted

技术标签:

【中文标题】iOS - 如何测量线程唤醒?【英文标题】:iOS - How to measure thread wakeups? 【发布时间】:2018-01-12 16:42:02 【问题描述】:

我有一个应用程序由于过多的“线程唤醒”而崩溃。例如:

过去 220 秒内有 45004 次唤醒(每次 205 次唤醒) 秒平均值),超过 300 秒内每秒 150 次唤醒的限制

这很难调试,因为我不知道测量线程唤醒的直接方法。我找到的最接近的是一个名为 System Trace 的 Instruments 模板,它会显示阻塞线程事件的数量。据推测,这是密切相关的,因为阻塞的线程意味着该线程将休眠,然后在解除阻塞时唤醒。

奇怪的是,当应用程序正常运行并且不崩溃时,阻塞线程的数量在每秒 10,000 的范围内。我的假设是,在某些情况下,阻塞的睡眠线程仅计入您的“唤醒”限制 - 例如我希望由于互斥锁而被锁定的线程计数,而操作系统在正常操作中简单地转换到其他线程不会。

如果 Instruments 有一个 Thread Wakeups 模板,我会很惊讶。我能找到的唯一文档在这里 - https://developer.apple.com/library/content/technotes/tn2151/_index.html:

异常子类型WAKEUPS表示进程中的线程每秒被唤醒太多次,这会迫使CPU非常频繁地唤醒并消耗电池寿命。

通常,这是由线程到线程通信(通常使用peformSelector:onThread:dispatch_async)引起的,这种通信在不知不觉中发生的频率远远超过应有的频率。由于触发此异常的通信发生得如此频繁,因此通常会有多个后台线程具有非常相似的Backtraces - 指示通信的来源。

【问题讨论】:

如果这是上下文切换的结果,您可能需要查看developer.apple.com/videos/play/wwdc2017/706,其中讨论了减少不必要的上下文切换的方法。 如果您想查看这些上下文切换,请使用 Instruments 的“系统跟踪”工具,您会在那里看到“上下文切换”。 是的,我们已经查看了系统跟踪工具并查看了上下文切换部分中的阻塞线程(根据描述)。没有“线程唤醒”,只有“阻塞”线程。 线程唤醒工具是个好主意。我建议每个人都提交一个雷达来实现这一点(我只是有,rdar://42114101)。 @Frederik ????;这是个好主意! 【参考方案1】:

请看这里https://developer.apple.com/forums/thread/124180 在您的应用程序中,不仅在仪器中,还有关于获取唤醒计数的代码的描述。可以帮助你:

#include <mach/task.h>
#include <mach/mach.h>
BOOL GetSystemWakeup(NSInteger *interrupt_wakeup, NSInteger *timer_wakeup) 
  struct task_power_info info = 0;
  mach_msg_type_number_t count = TASK_POWER_INFO_COUNT;
  kern_return_t ret = task_info(current_task(), TASK_POWER_INFO, (task_info_t)&info, &count);
  if (ret == KERN_SUCCESS) 
    if (interrupt_wakeup) 
      *interrupt_wakeup = info.task_interrupt_wakeups;
    
    if (timer_wakeup) 
      *timer_wakeup = info.task_timer_wakeups_bin_1 + info.task_timer_wakeups_bin_2;
    
    return true;
  
  else 
    if (interrupt_wakeup) 
      *interrupt_wakeup = 0;
    
    if (timer_wakeup) 
      *timer_wakeup = 0;
    
    return false;
  

您还可以找到唤醒次数过多的一些原因。

【讨论】:

以上是关于iOS - 如何测量线程唤醒?的主要内容,如果未能解决你的问题,请参考以下文章

您将如何测量多线程 C# 请求的响应时间? [关闭]

收到2个数据包后如何唤醒线程

重叠 I/O:如何在完成端口事件或正常事件上唤醒线程?

如何唤醒一个处于阻塞状态下的线程

在带有许多线程唤醒的 iOS 8 上并不总是显示 EXC_RESOURCE 崩溃?

我的多线程-多线程必知的N个常识