我遇到了一个非常奇怪的问题,影响我的代码仅在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's dispatch_after(,^{});
mach_wait_until()
无论我尝试使用何种延迟方法,我使用NSLog
将“延迟”值打印到控制台作为完整性检查以确保它是正确的ms,然后触发其中一个以上。它按照规范行事的时间约为95%。但偶尔随机,我会得到一些重击延迟,如10-20秒。是什么赋予了?这是一些优胜美地内核问题吗?再一次,我从来没有经历过在10.7上运行的相同代码。我已经测试了所有上述延迟代码执行的方法。
更新:
根据评论建议,我继续sudo dtruss -f -e sudo -u USER MyApp 2> ~/myapps.log
。像往常一样,大多数mach_wait和sleeps都按照预期的方式行事。因此,为了使事情更易于识别,我在检查中添加了实际睡眠持续时间是否>它应该是3倍,打印出DELAY ISSUE。跑我的程序,并搜索延迟问题。下面列出的是紧接在mach_wait语句之前和之后的日志打印之间发生的最频繁的系统调用(dtruss输出):
上述两个电话约有250+。可能比__semwait更多的工作。无论如何,semwait通常需要大约30000'单位'的时间才能完成。敦诺如何度过难关。这些构成了大部分电话。
这三个系统调用占用了最长的单位时间。在我们约20秒的等待间隙期间,它们每个都出现在输出中。
不确定如何处理上述= X
答案 0 :(得分:3)
见上面的评论
该问题似乎与Apple的计时器合并相关联,这是Mac OS X 10.9 Mavericks中的一项新功能,它可以将计时器的触发时间缩短几毫秒来合并它们,从而允许处理器可以减少电源状态转换并保持空闲时间更长。这样做的好处是大大降低了功耗。
Apple关于短暂提及的主题的白皮书是here。
评论中保留的解决方案是禁用TC,如下所示:
sudo sysctl -w kern.timer.coalescing_enabled=0