性能文章>优化 JavaScript 执行>

优化 JavaScript 执行转载

3月前
174200

JavaScript 经常会触发视觉变化。有时是直接通过样式操作,有时是会产生视觉变化的计算,例如搜索数据或将其排序。时机不当或长时间运行的 JavaScript 可能是导致性能问题的常见原因。您应当设法尽可能减少其影响。

JavaScript 性能分析可以说是一门艺术,因为您编写的 JavaScript 代码与实际执行的代码完全不像。现代浏览器使用 JIT 编译器和各种各样的优化和技巧来尝试为您实现尽可能快的执行,这极大地改变了代码的动态。

尽管如此,您肯定还是可以做一些事情来帮助您的应用很好地执行 JavaScript。

  • 动画效果的实现,避免使用 setTimeout 或 setInterval,请使用 requestAnimationFrame。
  • 将长时间运行的 JavaScript 从主线程移到 Web Worker。
  • 使用微任务来执行对多个帧的 DOM 更改。
  • 使用 Chrome DevTools 的 Timeline 和 JavaScript 分析器来评估 JavaScript 的影响。

当屏幕正在发生视觉变化时,您希望在适合浏览器的时间执行您的工作,也就是正好在帧的开头。保证 JavaScript 在帧开始时运行的唯一方式是使用 requestAnimationFrame

 
/**
 * If run as a requestAnimationFrame callback, this
 * will be run at the start of the frame.
 */

function updateScreen(time) {
 
// Make visual updates here.
}

requestAnimationFrame
(updateScreen);

框架或示例可能使用 setTimeoutsetInterval 来执行动画之类的视觉变化,但这种做法的问题是,回调将在帧中的某个时点运行,可能刚好在末尾,而这可能经常会使我们丢失帧,导致卡顿。

setTimeout 导致浏览器丢失帧。

事实上,jQuery 目前的默认 animate 行为是使用 setTimeout!强烈建议您打上补丁程序以使用 requestAnimationFrame

JavaScript 在浏览器的主线程上运行,恰好与样式计算、布局以及许多情况下的绘制一起运行。如果 JavaScript 运行时间过长,就会阻塞这些其他工作,可能导致帧丢失。

因此,您要妥善处理 JavaScript 何时运行以及运行多久。例如,如果在滚动之类的动画中,最好是想办法使 JavaScript 保持在 3-4 毫秒的范围内。超过此范围,就可能要占用太多时间。如果在空闲期间,则可以不必那么斤斤计较所占的时间。

在许多情况下,可以将纯计算工作移到 Web Worker,例如,如果它不需要 DOM 访问权限。数据操作或遍历(例如排序或搜索)往往很适合这种模型,加载和模型生成也是如此。

 
var dataSortWorker = new Worker("sort-worker.js");
dataSortWorker
.postMesssage(dataToSort);

// The main thread is now free to continue working on other things...

dataSortWorker
.addEventListener('message', function(evt) {
   
var sortedData = evt.data;
   
// Update data on screen...
});

并非所有工作都适合此模型: Web Worker 没有 DOM 访问权限。如果您的工作必须在主线程上执行,请考虑一种批量方法,将大型任务分割为微任务,每个微任务所占时间不超过几毫秒,并且在每帧的 requestAnimationFrame 处理程序内运行。

 
var taskList = breakBigTaskIntoMicroTasks(monsterTaskList);
requestAnimationFrame
(processTaskList);

function processTaskList(taskStartTime) {
 
var taskFinishTime;

 
do {
   
// Assume the next task is pushed onto a stack.
   
var nextTask = taskList.pop();

   
// Process nextTask.
    processTask
(nextTask);

   
// Go again if there’s enough time to do the next task.
    taskFinishTime
= window.performance.now();
 
} while (taskFinishTime - taskStartTime < 3);

 
if (taskList.length > 0)
    requestAnimationFrame
(processTaskList);

}

此方法会产生 UX 和 UI 后果,您将需要使用进度或活动指示器来确保用户知道任务正在被处理。在任何情况下,此方法都不会占用应用的主线程,从而有助于主线程始终对用户交互作出快速响应。

在评估一个框架、库或您自己的代码时,务必逐帧评估运行 JavaScript 代码的开销。当执行性能关键的动画工作(例如变换或滚动)时,这点尤其重要。

测量 JavaScript 开销和性能情况的最佳方法是使用 Chrome DevTools。通常,您将获得如下的简单记录:

Chrome DevTools 的 Timeline 提供简略的 JS 执行情况。

以这种方式分析 JavaScript 会产生开销,因此一定只在想要更深入了解 JavaScript 运行时特性时才启用它。启用此复选框后,现在可以执行相同的操作,您将获得有关 JavaScript 中调用了哪些函数的更多信息:

Chrome DevTools 的 Timeline 提供详细的 JS 执行情况。

有了这些信息之后,您可以评估 JavaScript 对应用性能的影响,并开始找出和修正函数运行时间过长的热点。如前所述,应当设法移除长时间运行的 JavaScript,或者若不能移除,则将其移到 Web Worker 中,腾出主线程继续执行其他任务。

知道浏览器执行一个函数版本比另一个函数要快 100 倍可能会很酷,比如请求元素的offsetTop比计算getBoundingClientRect()要快,但是,您在每帧调用这类函数的次数几乎总是很少,因此,把重点放在 JavaScript 性能的这个方面通常是白费劲。您一般只能节省零点几毫秒的时间。

如果您开发的是游戏或计算开销很大的应用,则可能属于本指南的例外情况,因为您一般会将大量计算放入单个帧,在这种情况下各种方法都很有用。

简而言之,慎用微优化,因为它们通常不会映射到您正在构建的应用类型。

分类:标签:
请先登录,感受更多精彩内容
快去登录吧,你将获得
  • 浏览更多精彩评论
  • 和开发者讨论交流,共同进步

为你推荐

优化 JavaScript 执行
JavaScript 经常会触发视觉变化。有时是直接通过样式操作,有时是会产生视觉变化的计算,例如搜索数据或将其排序。时机不当或长时间运行的 JavaScript 可能是导致性能问题的常见原因。您应当设法尽可能减少其影响。JavaScript 性能分析可以说是一门艺术,因为您编写的 JavaScr
如何通过 Core Web Vitals 阈值并实现整体跳出率提高 43%
随着互联网速度与日俱增,用户希望网站能够比以往更快地响应和运行。《经济时报》每月处理超过 4500 万活跃用户。通过针对整个域、AMP 和非 AMP 页面上的 Core Web Vitals 进行优化,我们设法显着降低了跳出率并改善了阅读体验。 衡量影响 我们专注于最大内
Redis 在 vivo 推送平台的应用与优化实践
一、推送平台特点 vivo推送平台是vivo公司向开发者提供的消息推送服务,通过在云端与客户端之间建立一条稳定、可靠的长连接,为开发者提供向客户端应用实时推送消息的服务,支持百亿级的通知/消息推送,秒级触达移动用户。 推送平台的特点是并发高、消息量大、送达及时性较高。目
使用 Lighthouse 优化 Web Vitals
今天,我们将介绍 Lighthouse、PageSpeed 和 DevTools 中的新工具功能,以帮助确定您的网站如何在Web Vitals上进行改进。 作为工具的复习,Lighthouse是一个开源的自动化工具,用于提高网页的质量。您可以在Chrome DevTools调试工具套件
QuintoAndar如何通过提高页面性能来提高每个会话的转化率和页面
QuintoAndar是一家巴西 proptech公司,其产品为房地产提供数字端到端解决方案。今年,我们开展了一个项目,专注于提高应用程序中内容中心的性能,并在增加用户流量和转化指标方面取得了令人鼓舞的成果。降低反弹率:46%每节课的页数增加:87%验证阶段转换的改进:5% 
使用 webpack 进行 Web 性能优化(三)
即使您配置 webpack 以使应用程序尽可能小,跟踪它并知道它包含什么仍然很重要。 否则,您可以安装一个使应用程序变大两倍的依赖项——甚至不会注意到它!本节介绍可帮助您了解捆绑包的工具。跟踪包大小要监控您的应用程序大小,请在开发期间使用 webpack-dashboa
使用 webpack 进行 Web 性能优化(二)
改善应用程序加载时间的下一件事(在优化应用程序大小之后)是缓存。 使用它将应用程序的某些部分保留在客户端上,并避免每次都重新下载它们。使用包版本控制和缓存标头进行缓存的常用方法:告诉浏览器将文件缓存很长时间(例如,一年): # Server headerCache-Contro
性能优化之html、css、js三者的加载顺序
前言我们知道一个页面通常由,html,css,js三部分组成,一般我们会把css文件放在head头部加载,而js文件则放在页面的最底部加载,想要知道为什么大家都会不约而同的按照这个标准进行构建页面,必须先得了解页面的加载过程。(当然以现在的技术你也可以不按这个标准,下面会有讲到js的异步加载问