성능 최적화 (1) Caton 최적화

함께 만들고 함께 성장하기 위해 함께 노력하십시오! "너겟 데일리 뉴플랜 · 8월 업데이트 챌린지" 참여 27일차 입니다 . 이벤트 상세보기 클릭

이 기사는 화면 정지의 원리를 추가로 분석하고 마지막으로 화면 정지를 해결하기 위해 Apple이 화면 하단에 그림을 렌더링하는 과정으로 시작합니다.

주요 내용:

  1. 양이온 원리
  2. 카톤 최적화
  3. 오프 스크린 렌더링

1. 카톤 원리

1.1 CRT 디스플레이의 원리

전자총은 위에서 아래로 한 줄씩 스캔하고 스캔이 완료되면 그림의 한 프레임이 되고 다음 스캔을 위해 초기 위치로 돌아가서 그림 표시를 구현합니다. 디스플레이는 스캔할 때마다 표시된 데이터를 가져와야 하므로 시스템의 비디오 컨트롤러와 동기화해야 합니다.디스플레이는 하드웨어 클록을 사용하여 동기화를 위한 일련의 타이밍 신호를 생성합니다.

타이밍 신호에는 두 종류가 있는데, 하나는 수평 동기 신호(HSync)이고 다른 하나는 수직 동기 신호(VSync)입니다.

드로잉 과정

  1. 각 라인을 스캔할 준비가 되면 HSync 신호가 방출됩니다.
  2. VSync 신호가 도착한 후 메인 스레드는 뷰 생성, 레이아웃 계산, 그림 디코딩, 텍스트 그리기 등을 포함하여 CPU의 콘텐츠를 계산하기 시작합니다. 계산된 콘텐츠는 GPU에 제출됩니다.
  3. GPU는 변환, 합성, 렌더링을 수행하고 렌더링 결과를 프레임 버퍼(frameBuffer)에 넣습니다.
  4. 비디오 컨트롤러는 다음 VSync 신호가 도착한 후 프레임 버퍼 데이터를 한 줄씩 읽습니다.
  5. 판독이 완료된 후 특정 디지털-아날로그 변환이 수행되고 디스플레이를 위해 디스플레이로 전달됩니다.
  6. 간단히 말해서 CPU 계산 및 GPU 렌더링 후 프레임 데이터는 프레임 버퍼 영역에 저장되고 비디오 컨트롤러는 프레임 버퍼 영역의 데이터를 읽고 디지털 후 디스플레이에 전달합니다. -아날로그 변환.
  7. 프레임이 완료되고 다음 프레임을 그릴 준비가 되면 VSync가 실행됩니다.

프로세스 다이어그램:

16612660728625.jpg

알아채다:

  • 디스플레이는 일반적으로 고정된 주파수, 즉 각 프레임이 완료되는 시간으로 화면을 새로 고칩니다.이 재생 빈도는 수직 동기 신호(VSync)입니다.

1.2 화면 표시의 원리

수직동기화 메커니즘을 주로 이해

如果只有一个帧缓冲区,帧缓冲区的读取和刷新都有较大的效率问题。因此通常需要引入双缓冲机制,也就是两个帧缓冲区,GPU会预先渲染好一帧放入到帧缓冲区,视频控制区进行读取,在读取的过程中,就可以将新渲染好的一帧放到另一个帧缓冲区,这样就可以一直不停的进行刷新帧缓冲区,而当视频控制器读取完成,GPU会主动的把指针指向第二个缓冲区,这样读取和刷新帧缓冲区的效率都提高了。

但上面的双缓冲机制有一个很大的问题,就是GPU会一直不停的将渲染好的一帧数据放到帧缓冲区中,并且在提交完成后,会主动的把指针指向第二个缓冲区,这样如果此时视频控制器还未读取完成,比如读取到一半,下一半就变成了下一帧的数据,就会造成画面撕裂现象。

正因为帧缓冲区的帧数据混用造成画面撕裂问题,需要引入垂直同步机制。也就是说,之前显示器只是把垂直水平信号同步到了视频控制器,垂直同步机制直接同步到了GPU

理解: GPU会等待显示器发出垂直水平信号(VSync)后,才进行新的一帧渲染和缓冲区更新

本质: 帧缓冲区的更新和读取时同时进行,而且都收到VSync信号的控制,读取上一个帧数据时,更新下一个帧数据

1.3 卡顿(掉帧)原理

在垂直同步机制下就会出现卡顿现象。

上面所说的垂直同步机制,需要VSync到来时,更新帧数据,下一个VSync到来时,会读取这次更新的帧数据。而如果下一个VSync到来时,因为CPU或GPU的原因,帧数据还没有更新到帧缓冲区,就会继续读取上一个帧数据,在一个VSync时间内显示了两次帧数据,就会造成卡顿现象。

CPU和GPU都会阻碍显示流程,都会造成掉帧现象

16612662691104.jpg

2. 卡顿优化

分为两类,CPU和GPU。

2.1 CPU资源消耗原因和解决方案

基本原则有两个:第一是避免使用不必要的操作,第二是必需的操作尽量放到后台执行。

避免不必要的操作:

  1. 对象创建
    1. 原因:对象的创建会分配内存、设置属性等操作比较消耗CPU资源,如果是反射机制就消耗的更多
    2. 解决:
      1. 使用轻量级的对象代替重量级的对象
      2. 推迟对象创建的时间,并把多个对象的创建分散到多个任务中,不要集中创建
      3. 如果对象可以复用,可以放到一个缓存池中复用
      4. 也就是说,如果用功能较少的对象可以完成任务,就不要用功能很多的对象了
    3. 例如:CALayer比UIVIew要轻量许多,如果不涉及事件响应,只需要显示,就可以用CALayer来代替UIView
  2. 纯代码编码
    1. 原因:storyboard创建视图对象消耗资源会比直接使用代码创建对象要大的非常多
    2. 解决:可以考虑使用纯代码编码
  3. 对象调整
    1. 原因:设置属性会消耗比较多的资源,所以需要避免频繁的设置属性
    2. 解决:尽量避免减少不必要的属性修改
    3. 例如:尤其是给UIView重设 属性时,比如frame时,其实都是设置了CALayer的属性,而CALayer是没有属性的,是通过方法动态解析实现的,临时为对象创建的一个属性,这非常消耗资源,所以应减少给UIView重置大小等操作
    4. 尽量避免调整视图层次,添加和移除视图,UIView、CALayer之间会出现很多方法调用与通知
  4. Autolayout
    1. 原因:对于复杂视图会产生严重的性能问题
    2. 解决:可以手动调整属性

必需的操作放到后台执行

  1. 对象销毁
    1. 原因:如果大量的对象进行销毁,也会占用一定的资源
    2. 解决:可以放到后台去释放对象
    3. 例如:在一个集合中保存有大量的对象,销毁这个集合时就会同时销毁这些对象,尽量放到后台去执行
  2. 布局计算
    1. 原因:视图布局的计算是最为常见的消耗CPU资源的地方
    2. 解决:可以在后台提前计算好视图布局,并进行缓存
    3. 例如:UIView的属性设置,尽量在后台计算好,一次性调整好属性
  3. 文本宽高计算
    1. 原因:文本的宽高计算会占用很大一部分资源,并且不可避免
    2. 解决:使用[NSAttributedString boundingRectWithSize:options:context:] 来计算文本宽高,用 -[NSAttributedString drawWithRect:options:context:] 来绘制文本,并且这两个方法需要放入到后台线程执行
    3. 也可以高度缓存
  4. 文本渲染
    1. 原因:所有的文本内容控件在底层都是通过CoreText实现的,而它的排版和绘制都是在主线程中,所以当显示大量文本的时候,CPU的压力会非常大
    2. 解决:在底层的CoreText对文本进行异步绘制
  5. 图片解码
    1. 原因:创建图片时,图片的数据并不会立即解码,而是在提交到GPU前CGImage中的数据才会得到解码,而且是在主线程中执行,所以会产生较多的消耗
    2. 解决:常见的做法是,先在后台把图片绘制到CGBITmapContext中,然后从bitmap直接创建图片

2.2 GPU资源消耗原因和解决方案

GPU:GPU是用图像处理器,它处理的内容都在显存中

消耗资源原因和解决方案

  1. 纹理的渲染
    1. 问题1:如果短时间内显示大量的图片,不管是提交到显存的过程,还是GPU进行渲染都要消耗不少GPU资源
    2. 解决1:尽量避免短时间内显示大量的图片,尽可能的将多张图片合成为一张进行显示
    3. 问题2:当图片过大,超过GPU的最大纹理尺寸,CPU会进行预处理,会对CPU和GPU带来额外的资源消耗
    4. 解决2:图片和视图大小不要超过纹理尺寸上限(4096*4096)
  2. 视图的混合
    1. 问题:多个视图叠在一起显示,GPU会首先把他们混合到一起再渲染,如果视图结构太过复杂,在混合的过程中也就会消耗资源了
    2. 解决:减少视图数量和层级
  3. 图像绘制
    1. 问题:CALayer的border、圆角、阴影、遮罩(mask)等显示通常会触发离屏渲染,GPU在进行离屏渲染就会消耗一定的资源
    2. 解决:
      1. 尽量使用已经设置好的图片,不用GPU去进行设置。
      2. 把需要显示的图形在后台线程回执未图片,避免使用圆角、阴影、遮罩等属性

3. 离屏渲染

오프 스크린 렌더링은 GPU가 렌더링을 위해 현재 스크린 버퍼 외에 새로운 오프 스크린 버퍼를 여는 것을 의미합니다.

레이어 렌더링을 완료하고 둥근 모서리, 그림자, 가우시안 흐림 등의 설정과 같은 일부 작업을 수행해야 할 때 이전에 프레임 버퍼에 저장된 프레임 데이터가 더 이상 존재하지 않으므로 오프- 저장을 위한 화면 버퍼 이러한 중간 상태에 대한 데이터.

모든 레이어가 오프 스크린 버퍼에 렌더링되면 각 오프 스크린 버퍼에서 데이터를 꺼내서 둥근 모서리 설정 등의 작업을 수행한 다음 결합하여 프레임 버퍼에 저장합니다.

장점과 단점:

오프 스크린 렌더링 비용

  1. 새로운 오프 스크린 버퍼를 열면 공간을 차지하고 리소스를 소비합니다.
  2. 컨텍스트 전환도 많은 리소스를 소모합니다.
  3. 오프 스크린 렌더링은 프레임 버퍼에 저장하기 전에 모든 레이어 작업이 설정될 때까지 대기하므로 시간이 오래 걸리고 끊김 현상이 발생하기 쉽습니다.

혜택:

  1. 여러 번 나타나는 데이터의 경우 재사용 목적을 달성하기 위해 미리 렌더링할 수 있습니다.
  2. 특수 효과, 중간 상태를 저장하기 위해 오프 스크린 버퍼를 사용해야 함

Supongo que te gusta

Origin juejin.im/post/7135368386841673764
Recomendado
Clasificación