grand-central-dispatch - 在 OSX 10.10 上延迟代码执行

标签 grand-central-dispatch osx-yosemite nsthread mach usleep

我遇到了一个非常奇怪的问题,该问题影响我仅在 OSX 10.10 系统上运行的代码。我已经在超过 25 个运行我的代码的 OSX 10.10 系统上看到过这种异常情况,而完全相同的代码在升级 (10.7) 之前并未表现出这种行为。此外,此问题并非 100% 可重现,因为它随机发生的概率约为 0-5%。在测试代​​码时,机器上没有发生任何其他关键或 CPU 耗尽的情况。即使发生了其他事情,我所经历的延误时间实在是太长了,这一事实使这个结论显得可疑。不管怎样,事不宜迟,看看下面的 NSLog 打印:

12:00:05.766 MyApp[59957:6540517] Time_To_Wait: 679000000, Fire_Date: 270946738287700, Cur_Date: 270946059302734
12:00:26.446 MyApp[59957:6540517] Resume...

时间以纳秒为单位。根据 NSLog 时间戳,我们实际上最终等待了 20.68 秒,而不是期望的 0.679 秒。现在,让我们看一下代码:

NSLog(@"Time_To_Wait: %lld, Fire_Date: %lld, Cur_Date: %lld", time_to_wait, fire_date, mach_absolute_time());
mach_wait_until(fire_date);
NSLog(@"Resume...");

如果您想知道 mach_wait 是什么,它是一个可用的默认高分辨率计时器。只需包含

#include <mach/mach.h>
#include <mach/mach_time.h>

但这并不重要,因为如果我将 mach_wait_until 替换为:

,我会遇到完全相同的问题
  • sleep ()
  • usleep()
  • [NSThread sleepForTimeInterval:]
  • GCD的dispatch_after(,^{});
  • mach_wait_until()

无论我尝试使用哪种延迟方法,我都会使用 NSLog 将我的“延迟”值打印到控制台作为健全性检查,以确保它是正确的毫秒数,然后触发上述其中一项。 ~95% 的时间其行为符合规范。但偶尔,我会遇到 10-20 秒之类的严重延迟。是什么赋予了?这是 Yosemite 内核问题吗?同样,我从未在 10.7 上运行相同的代码时遇到过这种情况。我已经测试了上述所有延迟代码执行的方法。


更新:

根据评论建议,我继续执行sudo dtruss -f -e sudo -u USER MyApp 2> ~/myapps.log。像往常一样,大多数 mach_wait 和 sleep 都按照预期的方式运行。因此,为了使事情更容易识别,我添加了一个检查,如果实际 sleep 持续时间 > 3 倍,它会打印出延迟问题。运行我的程序并搜索延迟问题。下面列出了在 mach_wait 语句之前和之后的日志打印之间发生的最频繁的系统调用(dtruss 输出):

  • 99613/0xcf33b9: 30250 __semwait_signal(0xD07, 0x0, 0x1) = -1 Err#60
  • 99613/0xcf33b9: 16 workq_kernreturn(0x20, 0x0, 0x1) = 0 0

上述两个调用大约有 250 多个。可能比 __semwait 多一些工作。 semwait 通常需要大约 30000 个“单位”的时间才能完成,无论是什么。不知道如何 dtruss 次。这些构成了大部分调用。

  • 752/0xcf3320: 2787191 kevent64(0x3, 0x0, 0x0) = 1 0
  • 752/0xcf335d: 189948 选择(0x40, 0x7FC080E18220, 0x7FC080E13B40, 0x0, 0x0) = 1 0
  • 752/0xcf335d: 1648403 选择(0x40, 0x7FC080E18220, 0x7FC080E13B40, 0x0, 0x0) = 1 0

这三个系统调用花费了最长的#个时间单位。在大约 20 秒的等待间隙中,它们分别在输出中出现一次。

不知道如何处理上面的=X

最佳答案

请参阅上面的评论

该问题似乎与苹果的计时器合并有关,这是 Mac OS X 10.9 Mavericks 中的一项新功能,可将计时器的触发时间调整最多几毫秒以将它们合并,从而允许处理器进行更少的电源状态转换并保持更长时间的空闲状态。这样做的好处是大大降低了功耗。

Apple 关于该主题的白皮书简要提到了它:here .

评论中保留的解决方案是禁用TC,如下:

sudo sysctl -w kern.timer.coalescing_enabled=0

关于grand-central-dispatch - 在 OSX 10.10 上延迟代码执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28785275/

相关文章:

swift - Swift GCD 覆盖中的类型不匹配

objective-c - ARC 的线程和对象生命周期

objective-c - 你如何在 NSWindow 上使用黑暗活力?

iphone - NSThreading 提高速度

ios - 快速创建线程?

ios - 当前队列、调度队列和目标队列在GCD中是如何相互通信的?

multithreading - CLLocationmanager从后台线程更新

swift - 并发队列中的 DispatchQueue 同步与同步屏障

ios - 使用 ionic 模拟 iOS,当前模拟失败,错误为 : Timed out waiting for device to boot.

php - OSX(Yosemite) 上的 Rails + MySQL