当前位置: 首页 > news >正文

Angular由一个bug说起之十二:网页页面持续占用CPU过高

随着网络日益发达,网页的内容也更加丰富,形式也更加多样化。而随之而来的性能问题也不容小觑。这篇文章我会根据我在实践中遇到的一个问题来总结,我在面对性能问题的一些解决步骤,希望能对大家有所启发。

查找问题原因

我接触的项目中有数据可视化的功能,在编辑可视化组件时页面会有明显卡顿,并且在页面加载完毕后也能感受到操作不流畅。

这种情况下我们一般使用排除法来查找出现问题的原因。首先查看 Devtool 是否有报错的情况,其次检查网络连接状况。

我使用的浏览器是 Chrome,如果有报错就会在 Console 里面观察到。网络状况我一方面使用 Ping 来测试服务器连接是否异常,另一方面选择下载文件(我下载的是 node.js)来测试网络速度,以此来判断是否网络问题造成的卡顿。

在我完成了对上面两点的检测后我就排除了由代码或网络引发这个问题的可能性。那么接下来很容易就让人想到是否性能出现了不合理的消耗。

关于性能,我们都知道网页所消耗的计算机资源第一是内存,第二是CPU。我用的系统是 Windows,而这两个指标可以在 Task Manager 中查看。

上图是相对正常时各指标的占用率或速率。当时我所观察到的情况是,内存保持在 50%-60% 的占用率,而 CPU 的占用率已经超过 95%,甚至到达 100%。那么原因就一目了然了,一定是出现了大量的需要计算的情况才导致页面卡顿。再考虑到页面在加载完成后依然保持极高的 CPU 占用率。

由此推断,最有可能的情况是:当前页面存在一个或多个不间断的监听事件,这些监听事件随着页面被加载而运行,导致 CPU 资源被持续占用。

解决过程

既然已经得出了一个合理的假设,那么就可以查看代码中是否存在持续调用的监听事件了。实际上,我在项目中发现了多处监听。

window.resize,mousemove,scroll,还包括钩子函数。这些都是在满足条件时会持续调用的方法,那么怎么确定是哪一个出现了问题呢?

我第一次判断是 window.resize 的问题,因为我在 window.resize 的回调函数中看到了一些 DOM 操作。这里其实应该做进一步的验证,但是我想当然的下了结论。我将 window.resize 删掉并测试结果,发现 CPU 占用率确实降低了,但是闲置时依然高达 60%。正常情况下这个数值应当不超过 10%。我意识到我的结论下的太早了,我需要更多的信息来找出真正的原因。

这时我想到可以借助工具,比如 Devtools。

使用 Chrome 的 Performance 来对页面的性能进行分析,结果如下:

这是从打开可视化编辑页面直到页面完全加载完毕的性能分析报告。从节选出的这部分可以看到一个叫 Animation frame 的 function 在持续的执行,问题肯定就出在它身上。

再次对代码进行查看后我将目标锁定在了 window.requestAnimationFrame() 上。

requestAnimationFrame

先来简单介绍 requestAnimationFrame:

它是一个浏览器的宏任务。 requestAnimationFrame 的用法与 setTimeout、setInterval 很相似,只是不需要设置时间间隔而已。requestAnimationFrame 使用一个回调函数作为参数,这个回调函数会在浏览器重绘之前调用。它返回一个整数,表示定时器的编号,这个值可以传递给 cancelAnimationFrame 用于取消这个函数的执行。

大多数电脑显示器的刷新频率是 60Hz,大概相当于每秒钟重绘 60 次。大多数浏览器都会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也不会有提升。因此最平滑动画的最佳循环间隔是1000ms/60,约等于 16.6ms。

在之前,为了实现动画,常常使用 setTimeout() 或 setInterval() 方法来定时更新动画帧。然而,这种方法并不理想,因为它们受限于定时器的精度和浏览器在不同设备上的性能差异。它们的内在运行机制决定了时间间隔参数实际上只是指定了把动画代码添加到浏览器 UI 线程队列中以等待执行的时间。如果队列前面已经加入了其他任务,那动画代码就要等前面的任务完成后再执行。

requestAnimationFrame 的出现解决了这个问题。它使用浏览器的刷新率作为参考,确保动画帧的更新在每一帧之间的间隔是最佳的,从而实现更加流畅和自然的动画效果。

requestAnimationFrame 引发的问题

如上所述,requestAnimationFrame 是一个类似于 setTimeout 或 setInterval 的方法。它虽然对性能更加友好,但是使用不当也会出现我们现在看到的问题。原因主要集中在 requestAnimationFrame 的回调函数。

requestAnimationFrame 作为一种高频发的事件,假如在回调函数中频繁的进行 DOM 操作,并且没有及时停止事件的触发,就会对性能造成巨大的影响。

项目中用到 requestAnimationFrame 的地方有两个,其中一个是 window.resize 另一个是 scroll。这也就是为什么我第一次尝试删掉 window.resize 的时候 CPU 占用率只下降到 60% 的原因。

接下来就是动手解决这个问题了。我发现 window.resize 中的 DOM 操作是为了给一个变量赋值,而这个变量在 scroll 的回调中被用到,而其它的代码已经失去了实际的作用。所以将两处代码整合,放弃使用 requestAnimationFrame,直接监听 scroll event。那么 requestAnimationFrame 也就可以删掉了。

做完这一切之后,再检测 Chrome 的 Performance 结果如下:

可以看到资源的消耗主要集中在加载页面的期间,而在闲置阶段不会过多的占用性能。

解决问题的方法不止一个,我之所以能直接删掉 requestAnimationFrame,而不担心破坏原有功能是因为项目中的这段代码已经没有实际作用了,属于历史遗留问题。

而如果我们要保证原有功能的正常运行,也有两个方案可以选择。

  1. 替代:requestAnimationFrame 往往被用于动画渲染方面的功能。尝试用 CSS 动画来代替它
  2. 优化:不在 requestAnimationFrame 的回调中做大量运算,在满足条件后及时的停止 requestAnimationFrame

总结

性能问题在实际项目中已经屡见不鲜,我们想改善项目的体验或者降低资源的消耗就必须要面对它。相对于常见的 bug 或者新增功能来说,解决性能问题更加的棘手。另外,在没有直接证据的情况下,不应该凭直觉来判断原因,而是多利用各种工具来解决问题。

为了方便入手解决以后可能遇到的类似问题,我将过程总结如下:

以上是我对此次资源占用问题的全部总结,谢谢。

相关文章:

Angular由一个bug说起之十二:网页页面持续占用CPU过高

随着网络日益发达,网页的内容也更加丰富,形式也更加多样化。而随之而来的性能问题也不容小觑。这篇文章我会根据我在实践中遇到的一个问题来总结,我在面对性能问题的一些解决步骤,希望能对大家有所启发。 查找问题原因 我接触的…...

【从零开始入门unity游戏开发之——C#篇05】转义字符、@处理多行文本或者不使用转义字符、随机数

文章目录 一、转义字符1、什么是转义字符?2、常见的转义字符3、总结 二、使用处理多行文本或者不使用转义字符1、多行字符串2、不使用转义字符 三、随机数1、Random.Next()生成随机整数示例:生成一个随机整数生成指定范围内的随机整数 2、Random.NextSin…...

我们来对接蓝凌OA --报文格式

题记 数智化办公专家、国家高新技术企业、知识管理国家标准制定者、信创供应商10强…等等,这些和咱们有关系吗!!不好意思,走错片场了,刚和项目经理在甲方那边吹牛B想想刚刚的大饼,看看支付宝余额&#xff…...

旅游系统旅游小程序PHP+Uniapp

旅游门票预订系统,支持景点门票、导游产品便捷预订、美食打卡、景点分享、旅游笔记分享等综合系统 更新日志 V1.3.0 1、修复富文本标签 2、新增景点入驻【高级版本】3、新增门票核销【高级版】4、新增门票端口【高级版】...

Pytest-Bdd-Playwright 系列教程(15):背景(Background)

Pytest-Bdd-Playwright 系列教程(15):背景(Background) 前言一、什么是背景(Background)二、特性文件三、测试脚本四、运行测试总结 前言 在测试的过程中,我们往往会遇到这样的问题&…...

ionic V6 安装ios所需

npm install capacitor/ios添加ios平台 ruby要求3.0以上 rvm use ruby-3.1.0 --default npx cap add ios打开xcode看看创建的项目 npx cap open ios没有capacitor指定的位置, 估计之前pod(cocoapods)安装搞得Ruby环境很乱了......cocoapods整的我麻了... App/App/capacitor…...

3d模型展示-初探

由于工作原因,近一年没怎么写代码,有朋友问你做过3D模型展示吗,之前都是做以vue为框架做定制业务,这次抽时间试试3d模型展示。 软件功能 使用ThreeJS框架实现加载GLB模型,并添加动画效果,实现3d展示模型。…...

OpenLinkSaas 2025年1月开发计划

先来看看OpenLinkSaas的大目标 在OpenLinkSaas的产品目标中,让开发人员更加方便的使用云资源是目标之一。通过各大云厂商的API,来可视化云上基础设施的数据是远远不够的。我们准备在2025年1月份增加方便管理和运营研发场景下服务器的能力。 这部分的功能…...

C# 用封装dll 调用c++ dll 使用winapi

这里用c net 封装winapi函数 pch.h // pch.h: 这是预编译标头文件。 // 下方列出的文件仅编译一次,提高了将来生成的生成性能。 // 这还将影响 IntelliSense 性能,包括代码完成和许多代码浏览功能。 // 但是,如果此处列出的文件中的任何一个…...

XML基础学习

参考文章链接: XML基础学习 在w3school看到了XML的教程,想到以前工作学习中也接触到了XML,但只是简单搜索了解了下,没有认真去学习XML的基础,所以现在认真看下其基础部分,并写篇博客作为笔记记录下。 XML 简介 XML 被设计用来传输和存储数据。 什么是 XML? XML 指可…...

Jmeter直连数据库,jar包下载

运行报错信息:jmeter连接mysql异常:Cannot load JDBC driver class ‘com.mysql.jdbc.Driver‘ 1、下载地址: https://mvnrepository.com/artifact/mysql/mysql-connector-java/ 2、将下载好的jar包 (我的是:mysql-con…...

Unity读取、新建Excel表格

把dll资源解压后,全部导入到unity中的Plugins文件下面 资源放在标题下方,可以自行下载 使用教程 引入命名空间 using SimpleExcel;。这个命名空间下主要有两个类:WorkBook和Sheet。WorkBook用于对整个excel文件的操作,如创建、打开…...

智能高效的IDE GoLand v2024.3全新发布——支持最新Go语言

GoLand 使 Go 代码的阅读、编写和更改变得非常容易。即时错误检测和修复建议,通过一步撤消快速安全重构,智能代码完成,死代码检测和文档提示帮助所有 Go 开发人员,从新手到经验丰富的专业人士,创建快速、高效、和可靠的…...

OpenCV相机标定与3D重建(21)投影矩阵分解函数decomposeProjectionMatrix()的使用

操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 将投影矩阵分解为旋转矩阵和相机内参矩阵。 cv::decomposeProjectionMatrix 是 OpenCV 库中的一个函数,用于将投影矩阵(…...

Flink State面试题和参考答案-(下)

如何监控 Flink 作业的状态大小? 监控 Flink 作业的状态大小是确保作业性能和稳定性的重要方面。以下是一些监控状态大小的方法: 使用 Flink Web UI: Flink 提供了一个 Web 用户界面,可以展示作业的当前状态大小,包括每个操作符…...

111.【C语言】数据结构之二叉树的销毁函数

目录 1.知识回顾 2.分析 3.代码 后序遍历销毁(最简洁) 前序遍历销毁(不推荐) 中序遍历销毁(不推荐) 4.将函数嵌入main函数中执行 1.知识回顾 106.【C语言】数据结构之二叉树的三种递归遍历方式 2.分析 销毁二叉树需要按照一定的顺序去销毁,例如:先销毁根还是先销毁根…...

[论文阅读] |智能体长期记忆与反思

写在前面:10月份的时候,联发科天玑9400发布,搭载这款旗舰 5G 智能体 AI 芯片的荣耀MagicOS9.0实现了一句话让手机自动操作美团点咖啡。很快商场实体店里便能看到很多品牌手机已经升级为智能体语音助手。下一步,这些智能体或许便能…...

【Trouble Shooting】Oracle ADG hung,出现ORA-04021

异常问题: 突然收到告警,ADG实例状态异常。 环境: 版本:Oracle 11.2.0.4.201020 状态:Active Dataguard 问题: 查看Oracle实例alert日志,发现有异常报错: Thu Dec 12 22:15:23 …...

基于springboot的招聘系统

文章目录 项目介绍主要功能截图:部分代码展示设计总结项目获取方式🍅 作者主页:超级无敌暴龙战士塔塔开 🍅 简介:Java领域优质创作者🏆、 简历模板、学习资料、面试题库【关注我,都给你】 🍅文末获取源码联系🍅 项目介绍 基于springboot的招聘系统,java项目。 e…...

国科大智能设备安全-APK逆向分析实验

APK逆向分析实验 使用APK常用逆向分析工具,对提供的移动应用程序APK文件进行逆向分析,提交逆向后代码和分析报告。具体任务如下: 任务一:安装并熟悉Apktool、Jadx等APK常用逆向工具的使用方法,对提供的Facebook Updat…...

使用SpaceDesk实现iPad成为电脑拓展屏(保姆级教程)

使用SpaceDesk实现iPad成为电脑拓展屏 在官网下载了最新的Windows和Android版本软件,时间:2024.10.23 22:36 https://lxhyouth.lanzouv.com/b0fov5nla 密码:lxhyouth SpaceDesk是一个开源的软件, 所以说对学生和平民用户非常的友好, 连接后的画质也非…...

Unity UI Button 事件优先级调整技术方案

Unity UI Button 事件优先级调整技术方案 在 Unity 项目开发过程中,针对 UI Button 的事件执行顺序控制是一个常见需求。本文详细阐述两种将新添加事件置于第一个执行位置的方法,旨在为开发者提供全面且专业的技术参考。 一、基于反射机制的事件插入方…...

算法训练营day1 | 704二分查找,27移除元素, 34, 35

已经找到工作,但希望再试试春招,距离春招还剩两个月,加油。 这两道题都刷过很多遍了,没什么好说的直接过。 704 本以为刷了很多次没想到还是做错了,有些小细节要注意。 这里是迭代式的,函数式的也不难。 …...

66 基于单片机的太阳能充电、温度检测、档位PWM调速系统

所有仿真详情导航: PROTEUS专栏说明-CSDN博客 目录 一、主要功能 二、硬件资源 三、主程序编程 四、资源下载 一、主要功能 基于52单片机,采用DS18B20温度传感器检测温度,采用滑动变阻器连接ADC0832数模转换器模拟电量,采用…...

RK3576 Android14,内存大于4G时UVC应用无法申请内存

最近有个项目需要将Linux虚拟成UVC摄像头,开发过程中遇到一个奇怪的事情,通过V4l2框架接口申请内存时,相同的板子,只是内存一个4G一个8G。4G的内存可以申请成功,8G就不行。提示“内存不足” 内存更大反而内存不足&…...

12.12 深度学习-卷积的注意力机制-通道注意力SENet

# 告诉模型训练的时候 对某个东西 给予额外的注意 额外的权重参数 分配注意力 # 不重要的就抑制 降低权重参数 比如有些项目颜色重要 有些是形状重要 # 通道注意力 一般都要比较多的通道加注意力 # SENet # 把上层的特征图 自动卷积为 1X1的通道数不变的特征图 然后给每一个…...

H5 scss 移动端的样式适配

在移动端样式的scss文件中,出现了这些变量 env() 与 constant() 设置安全区域,是css里IOS11新增的属性,webkit的css函数,用于设定安全区域与边界的距离,有4个预定义变量: safe-area-inset-left: 安全区域距…...

【JAVA】Java项目实战—移动端项目:天气查询APP

在移动互联网时代,天气查询应用程序(APP)是日常生活中不可或缺的一部分。无论是出门旅行、上班通勤,还是安排户外活动,获取实时天气信息都至关重要。Java作为一种强大且广泛使用的编程语言,特别适合用于开发…...

SpringBoot - 动态端口切换黑魔法

文章目录 关键技术点核心原理Code 关键技术点 利用 Spring Boot 内嵌 Servlet 容器 和 动态端口切换 的方式实现平滑更新的方案,关键技术点如下: Servlet 容器重新绑定端口:Spring Boot 使用 ServletWebServerFactory 动态设置新端口。零停…...

Java爬虫技术:挖掘淘宝数据的利器

在当今大数据时代,网络爬虫技术已经成为获取网络数据的重要手段。Java作为一种强大且灵活的编程语言,非常适合开发复杂的网络爬虫系统。本文将详细介绍Java爬虫能够爬取的淘宝数据类型,并提供具体的代码示例,帮助您快速入门并掌握…...