首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >你有没有注意到dispatch_after在iOS设备上运行速度太慢了10%?

你有没有注意到dispatch_after在iOS设备上运行速度太慢了10%?
EN

Stack Overflow用户
提问于 2014-01-21 18:15:53
回答 1查看 4.2K关注 0票数 22

最近,当我想在延迟后触发一些代码时,我一直在使用dispatch_after而不是性能选择器:withObject:afterDelay。代码更简洁,它可以访问封闭的范围,我可以将代码放在行中,而不是编写抛出方法等等。

我的代码可能如下所示:

代码语言:javascript
复制
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
  delay * NSEC_PER_SEC),
  dispatch_get_main_queue(),
  ^{
    //Delayed-execution code goes here.
  }
);

但是,我最近发现,这段代码的执行时间似乎比请求的慢了10%。如果我请求延迟10秒,大约11秒后我的块就会被执行。这是在一个iOS设备上。在模拟器上,时间似乎相当接近。

我用来测试这个的代码非常简单:

代码语言:javascript
复制
NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
  delay * NSEC_PER_SEC),
  dispatch_get_main_queue(),
  ^{
    NSTimeInterval actualDelay = [NSDate timeIntervalSinceReferenceDate] - startTime;
    NSLog(@"Requested delay = %.3f. Atual delay = %.3f", delay, actualDelay);
    //Delayed-execution code goes here.
  }
);

我在从iOS 4S到iPad Air的设备上进行了测试,额外的延迟是相当一致的。我还没有在像iPhone 4或iPad 2这样的旧设备上进行测试,不过我很快就会这样做。

我可能期望在延迟20-50毫秒的“懒散”,但一致的10% - 11%的超调是奇怪的。

我在代码中添加了一个“模糊因素”,以适应额外的延迟,但我感到惊讶的是:

代码语言:javascript
复制
#define  delay_fudge 0.912557 //Value calculated based on averages from testing.


NSTimeInterval startTime = [NSDate timeIntervalSinceReferenceDate];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW,
  delay * delay_fudge *  NSEC_PER_SEC),
  dispatch_get_main_queue(),
  ^{
    NSTimeInterval actualDelay = [NSDate timeIntervalSinceReferenceDate] - startTime;
    NSLog(@"Requested delay = %.3f. Actual delay = %.3f", delay, actualDelay);
    //Delayed-execution code goes here.
  }
);

我可能应该做更多的分析,看看是否有一个固定的增长延迟加上一个延迟因子或一个直接的延迟,或者一个非线性的比例的误差,但现在一个简单的乘数似乎做得很好。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-01-21 19:35:41

您可能听说过Timer Coalescing and App Nap --它有助于降低功耗。

您在这里观察到的是将系统事件延迟到某个“馀地值”的效果,以便能够在某个时间点执行所有这些事件,即“定时器合并”。这将增加CPU可以停留在其功率降低模式上的持续时间。

对于调度库,有一个标志可以用来提高"leeway值“的准确性,这最终也会影响计时器的准确性(见下文)。我不认为这是一个好主意,使定时器不必要的准确-例如移动设备。

我的怀疑是,dispatch_after将使用带有特定余地值集的调度计时器,该值集是定义的实现。

您可以使用dispatch_source_set_timer()使用调度库实现相当精确的定时器,其中还可以指定“馀量值”。

另见:dispatch/source.h

代码语言:javascript
复制
/*!
 * @typedef dispatch_source_timer_flags_t
 * Type of dispatch_source_timer flags
 *
 * @constant DISPATCH_TIMER_STRICT
 * Specifies that the system should make a best effort to strictly observe the
 * leeway value specified for the timer via dispatch_source_set_timer(), even
 * if that value is smaller than the default leeway value that would be applied
 * to the timer otherwise. A minimal amount of leeway will be applied to the
 * timer even if this flag is specified.
 *
 * CAUTION: Use of this flag may override power-saving techniques employed by
 * the system and cause higher power consumption, so it must be used with care
 * and only when absolutely necessary.
 */

#define DISPATCH_TIMER_STRICT 0x1

...

 * Any fire of the timer may be delayed by the system in order to improve power
 * consumption and system performance. The upper limit to the allowable delay
 * may be configured with the 'leeway' argument, the lower limit is under the
 * control of the system.
 *
票数 23
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21266022

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档