面试官:做过性能优化?我:任务切片!

news2025/1/22 18:53:20

 给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

代码背景

本次分享基于一次线上环境的卡顿事故,客户数据体量过大导致的页面卡顿甚至页面直接崩溃的问题。现在我们将会把此次事故抽象成为大家更好理解的案例,从而来进行分析和解决。

同时希望大家在阅读完之后可以了解到页面卡顿背后的底层原因,还有任务切片的解决原理!

<body>
    <input type="text">
    <button id="my-button">执行任务</button>
    <!-- box容器 -->
    <div id="box" style="height:500px;width:400px;overflow: auto;margin-top:24px;">
</body>
// box容器溢出滚动
const box = document.getElementById('box')
for(let i=0;i<1000;i++){
    const myText = document.createElement('h2')
    myText.innerText = i
    box.appendChild(myText)
}

// 执行任务
const myButton = document.getElementById('my-button')
myButton.addEventListener('click',load)
function load() {
  const total = 300000;
  for (let i = 0; i < total; i++) {
      console.log(i)
  }
}

点击执行任务按钮会发现,我们不仅不能和输入框进行交互,连box容器区域的滚动也不再有响应,整个页面卡顿住了,直到load任务执行完成,页面才恢复响应,输入框才能正常使用,box容器区域也能正常响应滚动。

或许观察到这里有人已经能够想到解决方案了!

我知道了,长任务执行导致页面卡顿,使用任务切片的方式解决!

没错,这里确实是使用任务切片的方式能够解决!但是,我想问一下,任务切片解决卡顿问题的底层原理是什么样子的?或者说什么是卡顿问题,而任务切片又是如何解决这类问题的?

卡顿分析

保证页面的流畅性是前端的一个主要内容,页面卡顿会严重影响用户体验。这流畅性是需要一个指标来衡量的,那就是帧率(FPS),FPS 表示的是每秒钟画面更新次数,当今大多数设备的屏幕刷新率都是60次/秒。

不同帧率的体验
  • 帧率能够达到 50 ~ 60 FPS 的动画将会相当流畅,让人倍感舒适;
  • 帧率在 30 ~ 50 FPS 之间的动画,因人敏感程度不同,舒适度因人而异;
  • 帧率在 30 FPS 以下的动画,让人感觉到明显的卡顿和不适感;
  • 帧率波动很大的动画,亦会使人感觉到卡顿

也就是说想要保证页面流畅不卡顿,浏览器对每一帧画面的渲染工作需要在16ms(1000ms/60)之内完成!

想要保证页面流畅,需要做到每16ms渲染一次!

也就是说,前面在我们执行任务的时候,浏览器没有能够做到每16ms渲染一次,所以我们页面会卡顿不流畅。那么是什么导致了浏览器没有能够正常渲染呢?或许在探索真相之前,我们还需要先深入了解一下浏览器的事件循环机制

浏览器事件循环机制

浏览器事件循环机制是一种用于处理异步任务的机制。它的工作原理是不断地检查任务队列,执行队列中的任务,并等待新的任务加入。

执行顺序:

  1. 执行宏任务队列和微任务队列就不解释了。

  1. 进入Update the rendering阶段,这里有个rendering opportunity概念,浏览上下文渲染会根据屏幕刷新率、页面性能、页面是否在后台来确定是否需要渲染。而且渲染间隔通常是固定的。

  2. 如果不需要渲染,以下步骤(只列举常用的)也不会运行了:

    • run the resize steps,触发 resize 事件;
    • run the scroll steps,触发 scroll 事件;
    • update animations,触发animation相关事件;
    • run the fullscreen steps,执行 requestFullscreen 等 api;
    • run the animation frame callbacks,执行 requestAnimationFrame 回调;
    • run IntersectionObserver callbacks,图片懒加载经常使用;
  3. 重新渲染用户界面。

  4. 判断宏任务队列或者微任务队列是否为空,如果为空则执行 Idle 空闲周期计算,判断是否需要执行 requestIdleCallback 的回调。

性能分析

通过我们上面对浏览器事件循环的深入了解,我们可以知道,浏览器没能每16ms渲染一次也能被解读为没能每16ms执行完一次事件循环

结合我们页面的Performance可以看到,load函数的执行花费了6s多,而事件循环中的渲染需要等待前面任务执行完毕,才会判断执行。

也就是说,浏览器花费了6s多的时间才完成了一次事件循环,完成了一次渲染任务,而我们保持页面60FPS的最低要求是每16ms完成一次渲染,这就难怪页面会卡顿不流畅,这显然是不合理的!

任务切片(setTimeout、requestAnimationFrame)

这就类似我们去餐厅吃饭,我们几个人很饿,点了很多菜给到厨房,但是厨房却等所有菜都做完(长任务执行)才全部一次性端上来(渲染),这样的体验毫无疑问是十分差劲的。

正确的做法应该是我们点了很多菜(一个长任务),厨房做完一道菜(小任务执行),就端上来一道(渲染一次),这样分多次上菜(多个小任务多次渲染)才不会让顾客等待太久,也能提升用户体验。

回到我们的页面代码,我们也可以按照这个思路,将load函数代码拆分成多个小任务,保证16ms内能执行完一次事件循环,这样才能保持页面流畅不卡顿,而这个时候,就需要应用到我们的任务切片了!

终于回到任务切片了!

一般我们可以使用setTimeout或者requestAnimationFrame实现任务切片,这里我们使用setTimeout举例说明:

function load() {
    let total = 1000000;
    let length = 20;
    let page = total/length
    let index = 0;
    function loop(curTotal,curIndex){
        if(curTotal <= 0){
            return false;
        }
        let pageCount = Math.min(curTotal , length);
        setTimeout(()=>{
            for(let i = 0; i < pageCount; i++){
                console.log(i)
            }
            loop(curTotal - pageCount,curIndex + pageCount)
        },0)
    }
    loop(total,index);
  }

此时我们运行代码之后发现,点击执行任务按钮时,页面不再卡顿,输入框能够正常focus交互,box容器区域也能正常滚动,一整个流畅!

我们再根据页面Performance进行分析:

可以看到,load函数代码分成了无数小任务(output)进行执行,每一次小任务执行完,都判断是否需要渲染(这里可以看到由于事件循环之间的间隔时间太短,浏览器选择三次事件循环才执行一次渲染任务)。此时我们浏览器就做到了每16ms完成一次渲染任务的指标,自然页面也就保持流畅不会有卡顿了!

最后总结

浏览器页面是否流畅取决于帧率FPS,帧率越高,页面越流畅,反之页面越卡顿。而页面帧率取决于浏览器执行渲染任务的频率(还有设备性能),同时我们知道,浏览器的渲染任务在事件循环中执行。因此我们想要页面流畅,就需要将事件循环花费的时间控制在16.7ms以内(一般设备)。

此时如果我们遇到长任务导致一次事件循环时间过长,我们可以使用任务切片的方式,将其分成多次小任务执行,保证每次事件循环的时间,便能够保证页面流畅!

 给大家推荐一个实用面试题库

1、前端面试题库 (面试必备)            推荐:★★★★★

地址:web前端面试题库

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

pdf压缩文件怎么压缩最小?

pdf压缩文件怎么压缩最小&#xff1f;我们很多项目介绍或是学术的报告都是采用的这个pdf格式&#xff0c;那么我们在存储或是需要进行分享的时候&#xff0c;可能就会因为文件过大而导致无法打开或是发送了。那么就需要将其进行压缩。PDF文件压缩方法很多&#xff0c;pdf压缩文…

【前端】JS - WebAPI

目 录 一.WebAPI 背景知识什么是 WebAPI什么是 APIAPI 参考文档 二.DOM 基本概念什么是 DOMDOM 树 三.获取元素querySelectorquerySelectorAll 四.事件初识基本概念事件三要素 五.操作元素获取/修改元素内容&#xff08;innerHTML&#xff09;获取/修改元素属性获取/修改样式属…

为什么全链路压测如此重要?

在今天的数字化世界中&#xff0c;软件系统的稳健性和性能至关重要。用户对于应用程序的高可用性和快速响应时间有着越来越高的期望&#xff0c;因此&#xff0c;全链路压测变得至关重要。本文将深入探讨什么是全链路压测&#xff0c;为什么它如此重要以及如何进行全链路压测。…

【ESP32】C语言映射表在嵌入式串口解析中的应用

本文章主要以ESP32开发环境为例记录&#xff0c;C语言映射表在嵌入式串口解析中的应用 【ESP32】C语言映射表在嵌入式串口解析中的应用 一、C语言映射表在串口数据解析中的应用1、数据结构2、指令、函数映射表3、串口解析函数实现 二、实验现象三、实验代码 一、C语言映射表在串…

Python超入门(4)__迅速上手操作掌握Python

# 15.while循环 rows 0 while rows < 5:print(* * rows)rows 1* ** *** ****# 16.使用while循环制作猜灯谜游戏secret_num 12 guess_count 0 guess_limit 100while guess_count < guess_limit:guess_count int(input("猜测:"))if guess_count secret_n…

turn搭建测试

安装 安装环境 cat /etc/redhat-release CentOS Linux release 7.6.1810 (Core)相关系统环境安装 sudo yum install -y make gcc cc gcc-c wgetsudo yum install -y openssl-devel libevent libevent-devel安装libEvent组件 # 如果链接不可用直接去官网找对应release包下载…

面试算法27:回文链表

问题 如何判断一个链表是不是回文&#xff1f;要求解法的时间复杂度是O&#xff08;n&#xff09;&#xff0c;并且不得使用超过O&#xff08;1&#xff09;的辅助空间。如果一个链表是回文&#xff0c;那么链表的节点序列从前往后看和从后往前看是相同的。 分析 如果不考虑…

使用两个goroutine交替、顺序打印一段字符串的字符

1、使用两个goroutine交替、顺序打印一段字符串的字符 输入&#xff1a;hello world 输出&#xff1a;hello world 关键点&#xff1a;控制goroutine的执行先后循序 golang语言版本&#xff1a; package mainimport ("fmt""sync" )func main() {conte…

数据结构——线性表作业

目录 选择题和填空题 编程题 1. 输出单链表倒数第K个结点值 单链表 双指针 2. 数组元素移动 3. 多项式相加 4. 数组的循环左移 选择题和填空题 编程题 1. 输出单链表倒数第K个结点值 【问题描述】 输入一个单向链表&#xff0c;输出该链表中倒数第k个结点&#xff0…

外贸知识:谈好订单的客户临时却要求价格优惠怎么办?

距离订单成交只差一步的时候&#xff0c;客户却要求价格一降再降&#xff0c;是为什么&#xff1f; 真的只是为了降价吗&#xff1f; Carl是一个苦苦挣扎的业务员&#xff0c;每次在挖掘客户需求的过程中&#xff0c;客户都是一副“对对对&#xff0c;是是是&#xff0c;好好好…

那些年,我们追过的Java BUG

&#x1f337;&#x1f341; 博主猫头虎 带您 Go to New World.✨&#x1f341; &#x1f984; 博客首页——猫头虎的博客&#x1f390; &#x1f433;《面试题大全专栏》 文章图文并茂&#x1f995;生动形象&#x1f996;简单易学&#xff01;欢迎大家来踩踩~&#x1f33a; &a…

基于springboot实现银行OA系统的设计与实现平台项目【项目源码+论文说明】计算机毕业设计

摘要 在互联网信息技术时代中&#xff0c;企业管理更多的是使用管理系统进行智能化控制&#xff0c;提高单位的核心竞争力&#xff0c;适应快节奏的生产活动。银行OA系统是为企业提供的一整套便于企业管理的应用软件&#xff0c;是目前企业管理的必备系统。通过走访了解&#…

几个非常实用的 Chrome Devtools 技巧

原文链接&#xff1a;[几个非常实用的 Chrome Devtools 技巧](https://fe32.top/articles/skill001/ 关于 Chrome 浏览器&#xff0c;如果你是一名前端开发者&#xff0c;相信对此并不陌生&#xff0c;我们可以用它来查看 网络请求、分析网页性能、调试 JavaScript 功能 等。 …

山海鲸报表系统:数据洞察的利器

在信息时代&#xff0c;数据是每个组织的核心资产。然而&#xff0c;拥有大量数据并不足够&#xff0c;我们需要将这些数据转化为有用的信息&#xff0c;以指导决策和行动。这就是山海鲸报表系统的使命。 解析数据的力量 山海鲸报表系统是一款强大的工具&#xff0c;旨在帮助企…

代码随想录打卡第四十二天| ● 62.不同路径 ● 63. 不同路径 II

62 不同路径 **题目&#xff1a;**一个机器人位于一个 m x n 网格的左上角 &#xff08;起始点在下图中标记为 “Start” &#xff09;。机器人每次只能向下或者向右移动一步。机器人试图达到网格的右下角&#xff08;在下图中标记为 “Finish” &#xff09;。 问总共有多少条…

收银系统哪个好 2023年十大收银软件品牌排行榜

根据2023年的最新数据和市场调研&#xff0c;以下是收银系统十大排名&#xff08;2023年十大收银软件品牌排行榜&#xff09;&#xff1a; 商人宝 一款集成了收银系统、会员管理、进销存和数据分析等多个功能的服装店收银软件&#xff0c;适用于服装卖场、中小型连锁超市、便利…

RunnerGo UI自动化使用体验

RunnerGo怎么做UI自动化 首先需要进入官网&#xff0c;RunnerGo支持开源&#xff0c;可以自行下载安装&#xff0c;也可以点击右上角体验企业版按钮快速体验 点击体验企业版进入工作台后可以点击页面上方的UI自动化 进入到测试页面 创建元素 我们可以在元素管理中创建我们测试…

企业文件防泄密软件!好用的文件加密系统推荐

由于众多企业内部都有大量的机密数据以电子文档的形式存储着&#xff0c;且传播手段多样&#xff0c;很容易造成文件泄密的问题发生。若是员工通过网络泄密重要文件&#xff0c;或是有黑客入侵窃取机密数据等&#xff0c;造成重要文件被非法查看盗取&#xff0c;都会给企业业务…

ROS 物体跟踪示例

物体跟踪与物体识别有相似之处&#xff0c;同样使用特征点检测的方法&#xff0c;但侧重点并不相同。物体识别针对的物体可以是静态的或动态的&#xff0c;根据物体特征点建立的模型作为识别的数据依据&#xff1b;物体跟踪更强调对物体位置的准确定位&#xff0c;输入图像一般…

2.2 如何使用FlinkSQL读取写入到文件系统(HDFS\Local\Hive)

目录 1、文件系统 SQL 连接器 2、如何指定文件系统类型 3、如何指定文件格式 4、读取文件系统 4.1 开启 目录监控 4.2 可用的 Metadata 5、写出文件系统 5.1 创建分区表 5.2 滚动策略、文件合并、分区提交 5.3 指定 Sink Parallelism 6、示例_通过FlinkSQL读取kafk…