iOS学习笔记optimize

iOS-卡顿监测-FPS监测(附详细代码及原理讲解)

2019-03-16  本文已影响0人  路飞_Luck
序言

一个应用的好坏很大程度上取决于使用是否流畅,所以明白造成应用卡顿的原因及解决思路显的至关重要。

一 检测的方案根据线程是否相关分为两大类:

与主线程相关的检测方案包括:

与主线程不相关的检测包括:

二 FPS 监测

通常情况下,屏幕会保持60hz/s的刷新速度,每次刷新时会发出一个屏幕刷新信号CADisplayLink允许我们注册一个与刷新信号同步的回调处理。可以通过屏幕刷新机制来展示fps值:

方法一

附核心代码

@implementation ViewController {
    UILabel *_fpsLbe;
    
    CADisplayLink *_link;
    NSTimeInterval _lastTime;
    float _fps;
}

- (void)startMonitoring {
    if (_link) {
        [_link removeFromRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
        [_link invalidate];
        _link = nil;
    }
    _link = [CADisplayLink displayLinkWithTarget:self selector:@selector(fpsDisplayLinkAction:)];
    [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
}

- (void)fpsDisplayLinkAction:(CADisplayLink *)link {
    if (_lastTime == 0) {
        _lastTime = link.timestamp;
        return;
    }
    
    self.count++;
    NSTimeInterval delta = link.timestamp - _lastTime;
    if (delta < 1) return;
    _lastTime = link.timestamp;
    _fps = _count / delta;
    NSLog(@"count = %d, delta = %f,_lastTime = %f, _fps = %.0f",_count, delta, _lastTime, _fps);
    self.count = 0;
    _fpsLbe.text = [NSString stringWithFormat:@"FPS:%.0f",_fps];
}

运行效果图

1.gif

监听count值的改变

#pragma mark - observer

- (void)addObserver {
    [self addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
    NSLog(@"count new = %@, old = %@",[change valueForKey:@"new"], [change valueForKey:@"old"]);
}
image.png

分析

1.通过打印,我们知道每次刷新时会发出一个屏幕刷新信号,则与刷新信号同步的回调方法`fpsDisplayLinkAction:`会调用,然后count加一。
2.每隔一秒,我们计算一次 `fps `值,用一个变量_lastTime记录上一次计算 fps 值的时间,然后将 count 的值除以时间间隔,就得到了 fps 的值,在将_lastTime重新赋值,_count置成零。
3.正常情况下,屏幕会保持60hz/s的刷新速度,所以1秒内`fpsDisplayLinkAction:`方法会调用60次。fps 计算的值为0,就不卡顿,流畅。
4.如果1秒内`fpsDisplayLinkAction:`只回调了50次,计算出来的fps就是 _count / delta(时间间隔) 。
方法二

核心代码

- (void)startFpsMonitoring {
    _link = [CADisplayLink displayLinkWithTarget: self selector: @selector(displayFps:)];
    [_link addToRunLoop: [NSRunLoop mainRunLoop] forMode: NSRunLoopCommonModes];
}

- (void)displayFps: (CADisplayLink *)fpsDisplay {
    self.count++;
    CFAbsoluteTime threshold = CFAbsoluteTimeGetCurrent() - _lastTime;
    if (threshold >= 1.0) {
        _fps = (_count / threshold);
        _lastTime = CFAbsoluteTimeGetCurrent();
        _fpsLbe.text = [NSString stringWithFormat:@"FPS:%.0f",_fps];
        self.count = 0;
        NSLog(@"count = %d,_lastTime = %f, _fps = %.0f",_count, _lastTime, _fps);
    }
}

运行结果和方法一差不多。

结论

image.png

本文参考 质量监控-卡顿检测,感谢该作者。


项目连接地址 - FpsMonitoring

上一篇下一篇

猜你喜欢

热点阅读