iOS卡顿原因与优化

iOS卡顿原因与优化

1. 卡顿简介

在这里插入图片描述

卡顿: 指用户在使用过程中出现了一段时间的阻塞,使得用户在这一段时间内无法进行操作,屏幕上的内容也没有任何的变化。

卡顿作为App的重要性能指标,不仅影响着用户体验,更关系到用户留存、DAU等重要产品数据。因此,需要关注APP的卡顿

2. 卡顿产生的原因

首先,屏幕上看到的所有内容都是计算机绘制出来的图像

帧率:Frames Per Second(fps),表示每秒渲染帧数,
通常用于衡量画面的流畅度,每秒帧数越多,则表示画面越流畅。

通常,60fps比较流畅,也就是60张/秒,每张图片需要的渲染时间大约是:
1s/60张 = 1000ms/60张 = 16.7ms/1张

也就是1张图像在16.7ms内出现一次,就不会造成卡顿现象。

在这里插入图片描述

在这里插入图片描述

  • CPU 中计算显示内容,比如视图的创建、布局计算、图片解码、文本绘制等
  • GPU 进行变换、合成、渲染,把渲染结果提交到帧缓冲区去,在下一次 VSync 信号到来时显示到屏幕上

在这里插入图片描述

卡顿产生的原因:当单位时间内,界面要刷新的时候,CPU或GPU由于计算量大,没有做好准备,
就会造成界面显示前一个时间段的界面,从而造成卡顿、掉帧现象

3. 如何避免卡顿

核心: 减少CPU、GPU的资源消耗

CPU

  1. 创建对象:对象的创建会分配内存、调整属性,因此,尽量使用轻量级的对象
  2. 布局计算:视图布局的计算是 App 中最为常见的消耗 CPU 资源的地方,不要频繁的调用UIView的相关属性;尽量提前计算好布局,在有需要时一次性调整到对应的属性,不要多次、频繁的计算和调整这些属性
  3. 线程处理:控制一下线程的最大并发数量;尽量把耗时的操作放到子线程,包括:文本计算、布局计算、图片的解码编码

GPU

  • 尽量避免短时间内大量图片的显示,尽可能将多张图片合成一张进行显示
  • GPU能处理的最大纹理尺寸是4096x4096,一旦超过这个尺寸,就会占用CPU的资源进行处理,所以纹理尺寸尽量不要超过这个尺寸
  • 尽量减少视图数量和层次
  • 减少透明的视图(alpha<1),不透明的就设置opaque为YES
  • 尽量避免出现离屏渲染

在OpenGL中,GPU有2种渲染方式:
1 当前屏幕渲染:在当前用于显示的屏幕缓冲区进行渲染操作
2 离屏渲染:在当前屏幕缓冲区以外新开辟一个缓冲区进行渲染操作

离屏渲染消耗性能的原因?
  • 需要创建新的缓冲区
  • 离屏渲染的整个过程,需要多次切换上下文环境,先是从当前屏幕(On-Screen)切换到离屏(Off-Screen);等到离屏渲染结束以后,将离屏缓冲区的渲染结果显示到屏幕上,又需要将上下文环境从离屏切换到当前屏幕
哪些操作会触发离屏渲染?
  • 光栅化,layer.shouldRasterize = YES
  • 遮罩,layer.mask
  • 圆角,同时设置layer.masksToBounds = YES、layer.cornerRadius大于0考虑通过CoreGraphics绘制裁剪圆角,或者叫美工提供圆角图片
  • 阴影,layer.shadowXXX,如果设置了layer.shadowPath就不会产生离屏渲染

4. 卡顿检测

  • 监控FPS
  • 监控RunLoop
  • ping主线程

4.1 监控FPS

帧率:Frames Per Second(fps),表示每秒渲染帧数

在这里插入图片描述

使用系统CADisplayLink监控,CADisplayLink是一个与屏幕刷新率相同的定时器,大约1/60s调用一次。

将其注册到RunLoop里面,计算当前画面的帧数。

delta为时间差等于1

在这里插入图片描述

4.2 监控RunLoop

由于UI刷新只能在主线程操作,因此,平时所说的“卡顿”,主要是因为主线程执行了比较耗时的操作

因此,可以添加observer到主线程Runloop中,通过监听Runloop状态切换的耗时,以达到监控卡顿的目的

在这里插入图片描述

RunLoop在BeforeSources和AfterWaiting后会进行任务的处理。可以在此时阻塞监控线程并设置超时时间,若超时后RunLoop的状态仍为RunLoopBeforeSources或AfterWaiting,表明此时RunLoop仍然在处理任务,主线程发生了卡顿

在这里插入图片描述

4.3 子线程Ping主线程

ping是常用的网络测试工具,用来测试数据包能否到达ip地址。
在这里插入图片描述

ping主线程的核心思想是向主线程发送一个信号,一定时间内收到了主线程的回复,即表示当前主线程流畅运行。
没有收到主线程的回复,即表示当前主线程在做耗时运算,发生了卡顿。

子线程Ping主线程的实现思路:

  1. 创建一个子线程进行循环检测,每次检测时设置标记位为YES
  2. 然后派发任务到主线程中将标记位设置为NO。
  3. 接着子线程休眠设定的阈值,判断标志位是否成功设置成NO,如果没有说明主线程发生了卡顿。

相当于:
子线程设置一个标识YES

如果发生了主线程的卡顿,那么到规定时间,主线程内的代码没有执行,则标识还是YES,这时候,代表卡顿
如果没有发生卡顿,那么到规定时间,主线程内的代码执行,则表示变为NO,这时候,代表没有发生卡顿

在这里插入图片描述

总结

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/267306.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

零拷贝技术深入分析

一、零拷贝 在前面的文章“深浅拷贝、COW及零拷贝”中对零拷贝进行过分析&#xff0c;但没有举例子&#xff0c;也没有深入进行展开分析。本文将结合实际的例程对零拷贝进行更深入的分析和说明。 在传统的IO操作中&#xff0c;以文件通过网络传输为例 &#xff0c;一般会经历以…

深度学习 精选笔记(4)线性神经网络-交叉熵回归与Softmax 回归

学习参考&#xff1a; 动手学深度学习2.0Deep-Learning-with-TensorFlow-bookpytorchlightning ①如有冒犯、请联系侵删。 ②已写完的笔记文章会不定时一直修订修改(删、改、增)&#xff0c;以达到集多方教程的精华于一文的目的。 ③非常推荐上面&#xff08;学习参考&#x…

并查集(Disjoint Set)

目录 1.定义 2.初始化 3.查找 4.合并 4.1.按秩合并&#xff08;启发式合并&#xff09; 5.例题 题目描述 输入格式 输出格式 输入输出样例 说明/提示 1.定义 并查集&#xff0c;也称为不相交集合数据结构&#xff0c;是一种用于管理元素分组以及查找元素所属组的数…

MWC 2024丨世界移动通信大会圆满结束,美格智能5G-A、端侧AI解决方案掀热潮

2月26日—29日&#xff0c;全球瞩目的2024世界移动通信大会&#xff08;MWC&#xff09;在西班牙巴塞罗那隆重举办。本届MWC以“未来先行”为主题&#xff0c;围绕“超越5G”、“智联万物”、“AI人性化”等话题展开&#xff0c;吸引了全球2400多家电信运营商、通信设备和终端制…

亿道信息新品EM-T195轻薄型工业平板,隆重登场!

EM-T195是一款轻巧但坚固的平板电脑&#xff0c;仅 650克重、10.5mm毫米厚&#xff0c;即使没有额外的便携配件进行辅助&#xff0c;您也可以轻松将其长时间随身携带。耐用性外壳完全密封&#xff0c;防尘防潮&#xff1b;出色的坚固性和可靠性&#xff0c;使T195天生适合在苛刻…

政府采购标书制作的要点解析

导语&#xff1a;政府采购是政府为满足公共利益&#xff0c;按照法定程序和标准&#xff0c;通过招标、竞争性谈判等方式&#xff0c;购买商品、工程和服务的行为。标书作为政府采购活动中的重要文件&#xff0c;其制作质量直接影响到项目的顺利进行。本文将围绕政府采购标书制…

导览系统厂家|景区电子导览|手绘地图|AR导览|语音导览系统

随着元宇宙、VR、AR等新技术的快速发展&#xff0c;旅游服务也更加多元化、智能化。景区导览系统作为旅游服务的重要组成部分&#xff0c;其形式更加多元化智能化。智能导览系统作为一种新的服务方式&#xff0c;能够为游客提供更加便捷的旅游服务和游览体验&#xff0c;也逐渐…

Android Gradle开发与应用 (四) : Gradle构建与生命周期

1. 前言 前几篇文章&#xff0c;我们对Gradle中的基本知识&#xff0c;包括Gradle项目结构、Gradle Wrapper、GradleUserHome、Groovy基础语法、Groovy语法概念、Groovy闭包等知识点&#xff0c;这篇文章我们接着来介绍Gradle构建过程中的知识点。 2. Project : Gradle中构建…

平台工程: 用Backstage构建开发者门户 - 1

本文介绍了如何使用开源Backstage构建自己的开发者门户&#xff0c;并基于此实践平台工程。本系列共两篇文章&#xff0c;这是第一篇。原文: Platform Engineering: Building Your Developer Portal with Backstage — Part 1 在上一篇文章(平台工程与安全)中&#xff0c;我们介…

Python实现PPT演示文稿中视频的添加、替换及提取

无论是在教室、会议室还是虚拟会议中&#xff0c;PowerPoint 演示文稿都已成为一种无处不在的工具&#xff0c;用于提供具有影响力的可视化内容。PowerPoint 提供了一系列增强演示的功能&#xff0c;在其中加入视频的功能可以大大提升整体体验。视频可以传达复杂的概念、演示产…

Linux - 基本开发工具

1、软件包管理器 yum 1.1、什么是软件包 在Linux下安装软件, 一个通常的办法是下载到程序的源代码, 并进行编译, 得到可执行程序但是这样太麻烦了, 于是有些人把一些常用的软件提前编译好, 做成软件包(可以理解成windows上的安装程序)放在一个服务器上, 通过包管理器可以很方…

泰迪智能科技企业数据挖掘平台使用场景

企业数据挖掘平台助力企业数据挖掘&#xff0c;数据挖掘平台也在多个领域发挥着重要的作用。 企业数据挖掘平台具有数据抓取、数据清洗、数据分析、机器学习等多项功能&#xff0c;广泛应用于企业的各个领域&#xff0c;包括&#xff1a;金融行业、医疗行业、交通领域、教育、制…

【SVN】使用TortoiseGit删除Git分支

使用TortoiseGit删除Git分支 前言 平时我在进行开发的时候&#xff0c;比如需要开发一个新功能&#xff0c;这里以蘑菇博客开发服务网关-gateway功能为例 一般我都会在原来master分支的基础上&#xff0c;然后拉取一个新的分支【gateway】&#xff0c;然后在 gateway分支上进…

SpringBoot:Invalid bound statement (not found)的原因和解决方案

&#x1f413; 报错信息&#xff1a; &#xff08;无效绑定声明&#xff09;找不到 解析&#xff1a; 你的mapper实例对象和对应的mapper.xml对象未找到 &#x1f413; 排查&#xff1a; 情况一&#xff1a; 1.排除相对应的mapper实例对象路径是否正确 查看相对应的mapper中…

无人机飞行控制系统技术,四旋翼无人机控制系统建模技术详解

物理建模是四旋翼无人机控制系统建模的基础&#xff0c;主要涉及到无人机的物理特性和运动学特性。物理建模的目的是将无人机的运动与输入信号&#xff08;如控制电压&#xff09;之间的关系进行数学描述。 四旋翼无人直升机是具有四个输入力和六个坐标输出的欠驱动动力学旋翼…

【前端素材】推荐优质后台管理系统网页Stisla平台模板(附源码)

一、需求分析 1、系统定义 后台管理系统是一种用于管理和控制网站、应用程序或系统的管理界面。它通常被设计用来让网站或应用程序的管理员或运营人员管理内容、用户、数据以及其他相关功能。后台管理系统是一种用于管理网站、应用程序或系统的工具&#xff0c;通常由管理员使…

kubectl 声明式资源管理方式

目录 介绍 YAML 语法格式 命令 应用yaml文件指定的资源 删除yaml文件指定的资源 查看资源的yaml格式信息 查看yaml文件字段说明 查看 api 资源版本标签 修改yaml文件指定的资源 离线修改 在线修改 编写yaml文件 创建资源对象 查看创建的pod资源 创建service服务对…

STL容器之string类

文章目录 STL容器之string类1、 什么是STL2、STL的六大组件3、string类3.1、string类介绍3.2、string类的常用接口说明3.2.1、string类对象的常见构造3.2.2、string类对象的容量操作3.2.3、string类对象的访问及遍历操作3.2.4、 string类对象的修改操作3.2.5、 string类非成员函…

【C++提高编程】

C提高编程 C提高编程1 模板1.1 模板的概念1.2 函数模板1.2.1 函数模板语法1.2.2 函数模板注意事项1.2.3 函数模板案例1.2.4 普通函数与函数模板的区别1.2.5 普通函数与函数模板的调用规则1.2.6 模板的局限性 1.3 类模板1.3.1 类模板语法1.3.2 类模板与函数模板区别1.3.3 类模板…

Redis源码安装教程来喽~

一.下载 Index of /releases/ [rootserver ~]# wget --no-check-certificate http://download.redis.io/releases/redis-6.2.7.tar.gz二.解压 [rootserver ~]# tar xf redis-6.2.7.tar.gz -C /usr/local/ [rootserver ~]# cd /usr/local [rootserver local]# ll 总用量 44K …