二、屏幕卡顿 及 iOS中的渲染流程解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
简介: 屏幕卡顿是指图形图像的在显示时出现了撕裂(即图片错位显示)、掉帧(重复显示同一帧数据)等问题,导致用户能直观的从屏幕上看到的一种异常现象

屏幕卡顿


屏幕卡顿是指图形图像的在显示时出现了撕裂(即图片错位显示)、掉帧(重复显示同一帧数据)等问题,导致用户能直观的从屏幕上看到的一种异常现象

为什么会出现这种情况呢?下面就来详细解说下屏幕卡顿


【高频面试题】屏幕卡顿的原因


主要有以下三种原因


  • CPU和GPU在渲染的流水线中耗时过长,导致从缓存区获取位图显示时,下一帧的数据还没有准备好,获取的仍是上一帧的数据,产生掉帧现象,掉帧就会导致屏幕卡顿
  • 苹果官方针对屏幕撕裂问题,目前一直使用的方案是垂直同步+双缓存区,可以从根本上防止和解决屏幕撕裂,但是同时也导致了新的问题掉帧。虽然我们采用了双缓存区,但是我们并不能解决CPU和GPU处理图形图像的速度问题,导致屏幕在接收到垂直信号时,数据尚未准备好,缓存区仍是上一帧的数据,因此导致掉帧
  • 在垂直同步+双缓存区的方案上,再次进行优化,将双缓存区,改为三缓存区,这样其实也并不能从根本上解决掉帧的问题,只是比双缓存区掉帧的概率小了很多,仍有掉帧的可能性,对于用户而言,可能是无感知的。


接下来,详细解析下屏幕撕裂及掉帧问题


屏幕撕裂


如图所示,屏幕撕裂就类似于这样的情形

微信图片_20220512215232.png

在讲屏幕撕裂之前,首先说说屏幕是如何成像的,主要的流程是什么


屏幕成像过程


请看下面这张图,详细说明了屏幕成像的一个流程

微信图片_20220512215551.png

  • 将需要显示的图像,经由GPU渲染
  • 将渲染后的结果,存储到帧缓存区,帧缓存区中存储的格式是位图
  • 由视屏控制器从帧缓存区中读取位图,交由显示器,从左上角逐行扫描进行显示


屏幕撕裂的原因



  • 在屏幕显示图形图像的过程中,是不断从帧缓存区获取一帧一帧数据进行显示的,
  • 然后在渲染的过程中,帧缓存区中仍是旧的数据,屏幕拿到旧的数据去进行显示,
  • 在旧的数据没有读取完时 ,新的一帧数据处理好了,放入了缓存区,这时就会导致屏幕另一部分的显示是获取的新数据,从而导致屏幕上呈现图片不匹配,人物、景象等错位显示的情况。
    图示如下:

微信图片_20220512215803.png


苹果官方的解决方案



苹果官方针对屏幕撕裂现象,目前一直采用的是 垂直同步+双缓存,该方案是强制要求同步,且是以掉帧为代价的。

以下是垂直同步+双缓存的一个图解过程,如有描述错误的地方,欢迎留言指出

微信图片_20220512220201.png


  • 垂直同步:是指给帧缓冲加锁,当电子光束扫描的过程中,只有扫描完成了才会读取下一帧的数据,而不是只读取一部分
  • 双缓冲区:采用两个帧缓冲区用途GPU处理结果的存储,当屏幕显示其中一个缓存区内容时,另一个缓冲区继续等待下一个缓冲结果,两个缓冲区依次进行交替


掉帧


采用苹果的双缓冲区方案后,又会出现新的问题,掉帧。

什么是掉帧?简单来说就是 屏幕重复显示同一帧数据的情况就是掉帧

如图所示:当前屏幕显示的是A,在收到垂直信号后,CPU和GPU处理的B还没有准备好,此时,屏幕显示的仍然是A

微信图片_20220512220355.png

  • 针对掉帧情况,我们可以在苹果方案的基础上进行优化,即采用三缓存区,意味着,在屏幕显示时,后面还准备了3个数据用于显示。


iOS中的渲染


在iOS中渲染的整体流程如下所示

微信图片_20220512220727.png

  • App通过调用CoreGraphics、CoreAnimation、CoreImage等框架的接口触发图形渲染操作
  • CoreGraphics、CoreAnimation、CoreImage等框架将渲染交由OpenGL ES,由OpenGL ES来驱动GPU做渲染,最后显示到屏幕上
  • 由于OpenGL ES 是跨平台的,所以在他的实现中,是不能有任何窗口相关的代码,而是让各自的平台为OpenGL ES提供载体。在ios中,如果需要使用OpenGL ES,就是通过CoreAnimation提供窗口,让App可以去调用。


iOS中渲染框架总结



主要由以下六种框架,表格中已经说明了,就不再详细解释了

微信图片_20220512220910.png

View 与 CALayer 的关系



首先分别简单说下UIView和CALayer各自的作用


UIView


  • UIView属于UIKIt
  • 负责绘制图形和动画操作
  • 用于界面布局和子视图的管理
  • 处理用户的点击事件


CALayer


  • CALayer属于CoreAnimation
  • 只负责显示,且显示的是位图
  • CALayer既用于UIKit,也用于APPKit,
    ==> UIKit是iOS平台的渲染框架,APPKit是Mac OSX系统下的渲染框架,
    ==> 由于iOS和Mac两个系统的界面布局并不是一致的,iOS是基于多点触控的交互方式,而Mac OSX是基于鼠标键盘的交互方式,且分别在对应的框架中做了布局的操作,所以并不需要layer载体去布局,且不用迎合任何布局方式。


【面试题】UIView和CALayer的关系


  • UIView基于UIKit框架,可以处理用户触摸事件,并管理子视图
  • CALayer基于CoreAnimation,而CoreAnimation是基于QuartzCode的。所以CALayer只负责显示,不能处理用户的触摸事件
  • 从父类来说,CALayer继承的是NSObject,而UIView是直接继承自UIResponder的,所以UIVIew相比CALayer而言,只是多了事件处理功能,
  • 从底层来说,UIView属于UIKit的组件,而UIKit的组件到最后都会被分解成layer,存储到图层树中
  • 在应用层面来说,需要与用户交互时,使用UIView,不需要交互时,使用两者都可以


UIView和CALayer的渲染


下图可以说明view 和 layer之间是如何渲染的

微信图片_20220512221206.png


  • 界面触发的方式有两种
    ==> 通过loadView中子View的drawRect方法触发:会回调CoreAnimation中监听Runloop的BeforeWaiting的RunloopObserver,通过RunloopObserver来进一步调用CoreAnimation内部的CA::Transaction::commit(),进而一步步走到drawRect方法
    ==> 用户点击事件触发:唤醒Runloop,由source1处理(__IOHIDEventSystemClientQueueCallback),并且在下一个runloop里由source0转发给UIApplication(_UIApplicationHandleEventQueue),从而能通过source0里的事件队列来调用CoreAnimation内部的CA::Transaction::commit();方法,进而一步一步的调用drawRect
    最终都会走到CoreAnimation中的CA::Transaction::commit()方法,从而来触发UIView和CALayer的渲染
  • 这时,已经到了CoreAnimation的内部,即调用CA::Transaction::commit();来创建CATrasaction,然后进一步调用 CALayer drawInContext:()
  • 回调CALayer的Delegate(UIView),问UIView没有需要画的内容,即回调到drawRect:方法
  • 在drawRect:方法里可以通过CoreGraphics函数或UIKit中对CoreGraphics封装的方法进行画图操作
  • 将绘制好的位图交由CALayer,由OpenGL ES 传送到GPU的帧缓冲区
  • 等屏幕接收到垂直信号后,就读取帧缓冲区的数据,显示到屏幕上

CoreAnimation


在苹果官方的描述中,Render、Compose,and animate visual elements,CoreAnimationg中的动画只是一部分,它其实是一个复合引擎,主要的职责包括 渲染、构建和动画实现。

ios中CoreAnimation如图所示


微信图片_20220512221447.png微信图片_20220512221447.png

微信图片_20220512221447.png


  • ios中基于CoreAnimation构建的框架有两个:UIKit和APPKit
  • CoreAnimation 又是基于Metal 、CoreGraphics封装的


苹果为什么要基于UIView和CALayer提供两个平行的层级关系(UIKit 和APPKit)?


  • 职责分离,可以避免大量重复代码
  • 两个系统交互规则不一致,虽然功能上类似,但实现上有显著区别

CoreAnimation中的渲染流水线


CoreAnimation中渲染的流程如图所示

微信图片_20220512221748.png

主要分为两部分:

  • CoreAnimation部分
  • GPU部分


CoreAnimation部分


  • App处理UIView、UIButton等载体的事件,然后通过CPU完成对显示内容的计算,并将计算后的图层进行打包,在下一次runloop时,发送到渲染服务器
  • Render Server中主要对收到的准备显示的内容进行解码,然后执行OpenGL等相关程序,并调用GPU进行渲染
    ==> Render Server 操作分析

微信图片_20220512221944.png

GPU部分


  • GPU中通过顶点着色器、片元着色器完成对显示内容的渲染,将结果存入帧缓存区
  • GPU通过帧缓存区、视频控制器等相关部件,将其显示到屏幕上
相关文章
|
15天前
|
监控 安全 开发工具
鸿蒙HarmonyOS应用开发 | HarmonyOS Next-从应用开发到上架全流程解析
HarmonyOS Next是华为推出的最新版本鸿蒙操作系统,强调多设备协同和分布式技术,提供丰富的开发工具和API接口。本文详细解析了从应用开发到上架的全流程,包括环境搭建、应用设计与开发、多设备适配、测试调试、应用上架及推广等环节,并介绍了鸿蒙原生应用开发者激励计划,帮助开发者更好地融入鸿蒙生态。通过DevEco Studio集成开发环境和华为提供的多种支持工具,开发者可以轻松创建并发布高质量的鸿蒙应用,享受技术和市场推广的双重支持。
194 11
|
2月前
|
Java 开发工具 Android开发
Android与iOS开发环境搭建全解析####
本文深入探讨了Android与iOS两大移动操作系统的开发环境搭建流程,旨在为初学者及有一定基础的开发者提供详尽指南。我们将从开发工具的选择、环境配置到第一个简单应用的创建,一步步引导读者步入移动应用开发的殿堂。无论你是Android Studio的新手还是Xcode的探索者,本文都将为你扫清开发道路上的障碍,助你快速上手并享受跨平台移动开发的乐趣。 ####
|
18天前
|
域名解析 弹性计算 安全
阿里云服务器租用、注册域名、备案及域名解析完整流程参考(图文教程)
对于很多初次建站的用户来说,选购云服务器和注册应及备案和域名解析步骤必须了解的,目前轻量云服务器2核2G68元一年,2核4G4M服务器298元一年,域名注册方面,阿里云推出域名1元购买活动,新用户注册com和cn域名2年首年仅需0元,xyz和top等域名首年仅需1元。对于建站的用户来说,购买完云服务器并注册好域名之后,下一步还需要操作备案和域名绑定。本文为大家展示阿里云服务器的购买流程,域名注册、绑定以及备案的完整流程,全文以图文教程形式为大家展示具体细节及注意事项,以供新手用户参考。
|
2月前
|
缓存 监控 Java
Java线程池提交任务流程底层源码与源码解析
【11月更文挑战第30天】嘿,各位技术爱好者们,今天咱们来聊聊Java线程池提交任务的底层源码与源码解析。作为一个资深的Java开发者,我相信你一定对线程池并不陌生。线程池作为并发编程中的一大利器,其重要性不言而喻。今天,我将以对话的方式,带你一步步深入线程池的奥秘,从概述到功能点,再到背景和业务点,最后到底层原理和示例,让你对线程池有一个全新的认识。
57 12
|
1月前
|
存储 安全 数据安全/隐私保护
深入解析iOS 14隐私保护功能:用户数据安全的新里程碑
随着数字时代的到来,个人隐私保护成为全球关注的焦点。苹果公司在最新的iOS 14系统中引入了一系列创新的隐私保护功能,旨在为用户提供更透明的数据使用信息和更强的控制权。本文将深入探讨iOS 14中的几项关键隐私功能,包括App跟踪透明性、简化的隐私设置以及增强的系统安全性,分析它们如何共同作用以提升用户的隐私保护水平。
92 3
|
1月前
|
Java 调度 Android开发
安卓与iOS开发中的线程管理差异解析
在移动应用开发的广阔天地中,安卓和iOS两大平台各自拥有独特的魅力。如同东西方文化的差异,它们在处理多线程任务时也展现出不同的哲学。本文将带你穿梭于这两个平台之间,比较它们在线程管理上的核心理念、实现方式及性能考量,助你成为跨平台的编程高手。
|
2月前
|
数据安全/隐私保护 iOS开发 开发者
iOS 14隐私保护新特性深度解析####
随着数字时代的到来,隐私保护已成为全球用户最为关注的问题之一。苹果在最新的iOS 14系统中引入了一系列创新功能,旨在增强用户的隐私和数据安全。本文将深入探讨iOS 14中的几大隐私保护新特性,包括App跟踪透明度、剪贴板访问通知和智能防追踪功能,分析这些功能如何提升用户隐私保护,并评估它们对开发者和用户体验的影响。 ####
|
2月前
|
开发框架 Dart Android开发
安卓与iOS的跨平台开发:Flutter框架深度解析
在移动应用开发的海洋中,Flutter作为一艘灵活的帆船,正引领着开发者们驶向跨平台开发的新纪元。本文将揭开Flutter神秘的面纱,从其架构到核心特性,再到实际应用案例,我们将一同探索这个由谷歌打造的开源UI工具包如何让安卓与iOS应用开发变得更加高效而统一。你将看到,借助Flutter,打造精美、高性能的应用不再是难题,而是变成了一场创造性的旅程。
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
87 2
|
12天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

推荐镜像

更多