是什么原因导致CADisplayLink偶尔会被解雇/延迟?

时间:2013-12-20 16:17:32

标签: ios timer cadisplaylink

也许您不需要所有这些信息来帮助我解决这个问题。核心问题是:什么可能导致CADisplayLink延迟开火,以及如何检查可能的原因?

我正在使用CADisplayLink计时器来速度 - 惯性 - 滚动我自己的音频波形视图实现:

- (void) startVelocityScrollTimer {
    dispatch_sync(dispatch_get_main_queue(), ^{
        if (_velocityScrollTimer == nil) {
            _velocityScrollTimer = [CADisplayLink displayLinkWithTarget:self selector:@selector(velocityScroll)];
            _velocityScrollTimer.frameInterval = 1;
            [_velocityScrollTimer addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
        }
    });
}

我遇到计时器准确性方面的问题。它通常每秒发射50或60次(不确定,但确切的数字在这里无关紧要)。在某些动作期间,此速率降至每秒约3至5次发射,这对于平滑滚动而言太低。我无法确定造成这些延误的原因。

我试过了:

  • 通过将音频数据加载到专用的调度队列来完全解耦绘图和加载,该队列以异步方式加载数据。
  • 分析和优化绘图方法。在峰值时,最多需要6ms。
  • 分析定时器触发时调用的方法(velocityScroll :)。通常执行时间不到1毫秒,有时峰值为3毫秒。
  • 使用NSRunLoopCommonModes代替NSDefaultRunLoopMode CADisplayLink计时器

在缓存中,我有很多dispatch_sync和一些dispatch_barrier_sync。虽然大多数都应该是无关紧要的,但我已经

  • 在我的缓存中描述每个调度到开始时间
  • 描述了缓存中分派块的每个执行时间

虽然他们中的大多数必须是无关紧要的。我没有发现任何超过50毫秒的等待/阻塞。这有点慢,但我认为不应该把定时器降到5火/秒或更差。

对于分析,我没有使用分析工具(无法处理它们)。相反,我使用了典型的方法:

double start = CACurrentMediaTime();

// code to profile here

NSLog(@"it took %.2fms", (CACurrentMediaTime() - start) * 1000);

这是计时器触发时执行的方法。中间的三种方法大多是简单的简单位置计算,几乎没有时间执行,除了最后一个,它执行dispatch_sync到主队列。但是,这完成得非常快(不到3毫秒,见上文)。

- (void) velocityScroll {
    Float32 cyclesPerSecond = 1.0 / _velocityScrollTimer.duration;

    [self applyScrollVelocityToScrollPosition:cyclesPerSecond];
    [self applyScrollVelocityDecelerationToScrollVelocity:cyclesPerSecond];
    [self ensureVelocityScrollOnlyActiveIfNeeded];

    [self setNeedsDisplay];
}

我知道你们想看到更多代码,但是有很多代码,我不想发布所有代码。如果您需要,请询问个别部件,我将在此处发布。

什么可能导致CADisplayLink计时器触发之间的延迟或如何找到它?

0 个答案:

没有答案