如何在iOS ProMotion设备上获取帧率并区分CADisplayLink回调卡顿与帧率切换
如何在iOS ProMotion设备上获取帧率并区分CADisplayLink回调卡顿与帧率切换
嘿,这个问题确实是ProMotion设备做性能监控时的棘手难题——毕竟系统动态切换帧率时,CADisplayLink的回调间隔变化和卡顿导致的延迟看起来几乎一样。结合你提到的iOS 15的特殊情况,我来分享几个实际验证过的可行思路:
利用
preferredFrameRateRange的min/max结合实际帧间隔判断
虽然iOS 15里CADisplayLink.preferredFrameRateRange.preferred会返回0,但minimum和maximum字段是实时更新的,能反映当前系统允许的帧率范围。你可以这么做:- 每次回调时,用当前帧的
timestamp减去上一帧的timestamp,计算出实际帧间隔,再转换成实际帧率(1 / 帧间隔)。 - 对比当前的
minimum和maximum值:如果实际帧率落在这个范围附近(可以加±1的容错,避免微小波动误判),那就是系统在切换帧率档位;如果实际帧率远低于minimum,那大概率是卡顿。
- 每次回调时,用当前帧的
通过连续帧的稳定性辅助判断
有时候单帧的间隔波动可能是系统帧率切换的过渡,这时候可以多记录几帧的间隔:- 如果连续2-3帧的间隔都稳定在某个新的帧率对应的数值,且和当前
min/max范围匹配,就判定为帧率切换。 - 如果连续多帧间隔都远超当前范围的预期值,再判定为卡顿,这样能减少误判。
- 如果连续2-3帧的间隔都稳定在某个新的帧率对应的数值,且和当前
附一段参考代码示例
class FramePerformanceMonitor { private var displayLink: CADisplayLink? private var lastTimestamp: CFTimeInterval = 0 // 记录连续帧的间隔,用于辅助判断 private var recentFrameIntervals = [CFTimeInterval]() func startMonitoring() { displayLink = CADisplayLink(target: self, selector: #selector(onDisplayLinkTick(_:))) displayLink?.add(to: .main, forMode: .common) } func stopMonitoring() { displayLink?.invalidate() displayLink = nil } @objc private func onDisplayLinkTick(_ link: CADisplayLink) { guard lastTimestamp > 0 else { lastTimestamp = link.timestamp return } let currentInterval = link.timestamp - lastTimestamp lastTimestamp = link.timestamp // 维护最近3帧的间隔记录 recentFrameIntervals.append(currentInterval) if recentFrameIntervals.count > 3 { recentFrameIntervals.removeFirst() } let actualFps = 1 / currentInterval let frameRange = link.preferredFrameRateRange let minAllowedFps = frameRange.minimum let maxAllowedFps = frameRange.maximum // 计算最近帧的平均帧率 let avgInterval = recentFrameIntervals.reduce(0, +) / Double(recentFrameIntervals.count) let avgFps = 1 / avgInterval // 判断是否是帧率切换:平均帧率落在允许范围内,且单帧波动小 let isFrameRateShift = avgFps >= minAllowedFps - 1 && avgFps <= maxAllowedFps + 1 if isFrameRateShift { print("系统切换帧率:当前平均帧率 \(avgFps),允许范围 \(minAllowedFps)-\(maxAllowedFps)") } else { print("出现卡顿:当前平均帧率 \(avgFps),远低于允许范围最小值 \(minAllowedFps)") } } }注意事项
- ProMotion设备的帧率范围是动态变化的,比如显示静态内容时可能降到10Hz左右,滑动时回升到120Hz,每次回调都要实时获取最新的
min/max值。 - 容错范围可以根据自己的监控需求调整,比如对游戏类应用可以把容错调小,对普通应用可以适当放宽。
- ProMotion设备的帧率范围是动态变化的,比如显示静态内容时可能降到10Hz左右,滑动时回升到120Hz,每次回调都要实时获取最新的
内容来源于stack exchange
相关产品推荐
相关产品推荐

