生成式AI领域的最新成果都在这里!抢 QCon 展区门票 了解详情
写点什么

JavaScript 的成本

  • 2018-01-02
  • 本文字数:3946 字

    阅读完需:约 13 分钟

在建立那些严重依赖于 JavaScript 网站的时候,有时我们会为自己发送的内容付出一些隐形的成本。在本篇文章中,我会介绍一些可以帮助你提升网站在移动设备上加载和运行速度的实用规则

tl;dr:更少的代码 = 更少的解析 / 编译 (parse/compile)+ 更少的传送 + 更少的解压缩

网络

大多数开发人员考虑 JavaScript 成本的时候,考虑的都是下载和执行成本。通过线路发送的 JavaScript 字节越多,所需时间就越长,用户连接就越慢。

即使是在发达国家,这也可能是一个问题,因为用户实际上用的有效网络连接类型可能并不是 3G、4G 或者 Wifi。表面上你可能连的是咖啡店的 Wifi,但实际上连到的是只有 2G 速度的蜂窝热点。

你可以通过以下的几种方式来降低 JavaScript 的网络传输成本:


(减少向用户发送 JavaScript 量的最佳做法。)

解析 / 编译

下载成功后,JavaScript** 绝大部分的时间都消耗在 JS 引擎对下载代码的解析 / 编译 ** 上。在 Chrome DevTools 中,解析和编译是下面性能面板(Performance panel)中黄色“脚本”时间的一部分。

Bottom-Up/Call Tree 允许我们去确切地查看解析 / 编译所用时间:


Chrome DevTools 性能面板下级菜单 >Bottom-U。启动 V8 的 Runtime Call Stats,就能看到不同阶段的时间消耗,比如解析 / 编译所用时间。

但是,这为什么会是个问题?

耗费很长的时间在解析 / 编译代码上,会严重延迟用户与你网站的交互时间。你发送的 JavaScript 越多,在网站实现交互前所用的解析 / 编译的时间就会越长

即使是同样多的字节,浏览器处理 JavaScript 也会比处理等大小的图片和网页字体消耗更高的成本——Tom Dale

相比于 JavaScript,处理等字节的图片所需要的时间成本很高(因为图片仍需要解码!)但是在一般的移动设备上,反而是 JS 更有可能对页面的交互产生负面的影响。


(JavaScript 字节和图像字节耗费的时间成本不同。图像通常不会阻塞主线程,也不会在解码和光栅化的时候阻止接口进行交互。然而 JS 会因为解析、编译和执行的时间消耗阻滞交互性。)

当我们说解析和编译的速度变慢的时候,要注意具体的网络端和设备端的情况,在这里我们针对的是普通手机。普通用户所使用手机的 CPU 和 GPU 速度比较慢,没有 L2/L3 缓存,甚至可能会有内存限制。

网络功能和设备功能并不总是相匹配的。有速度惊人的光纤连接的用户不一定会有最好的 CPU 来解析和评估发送到他们的设备的 JavaScript。反过来也是如此…你可能有糟糕的网络连接,但却有快速的 CPU。 - Kristofer Baxter,LinkedIn

JavaScript Start-up Performance 一文中,我曾提到过在低端和高端硬件上解析~1MB 解压缩过(简单)的 JavaScript 所需要消耗的时间。市面上的普通手机和运行速度最快的手机相比,解析 / 编译代码的所用的时间会有 2-5 倍的差距。


(在不同级别的台式和移动设备上解析 1MB 的 JavaScript 包(经 gzip 压缩,大小约为 250KB )。当分析解析成本时,我们需要考虑的是解压后的数据量,例如〜250KBgzip 压缩过的 JS 解压缩后约为〜1MB 的代码。)

那解析 / 编译真实网站的时间差异又会是怎样呢,比如 CNN.com 网站?

在高端的 iPhone 8 上解析 / 编译 CNN 网站的 JS 大约花费了 4 秒,相比于普通手机(Moto G4)的 13 秒左右。这可以显著地影响用户与 CNN 网站实现完全交互的速度。


(苹果公司的 A11 仿生芯片和更普通的 Android 硬件中的 Snapdragon 617 的解析时间上的性能比较

这就突出了在普通硬件(比如 Moto G4)上测试的重要性,而不仅仅是在自己恰好有的手机上测试。基于 _ 自己 _ 客户原有的设备和网络条件来进行优化是很重要的。

分析可以使你更加深入了解自己真实客户访问网站所用的移动设备的级别和这些设备 CPU/GPU 的局限性。

我们真的发送了太多的 JavaScript 了吗?呃…真有可能:)

用 HTTP Archive(qian500K 站点)来分析移动设备上 JavaScript 的状态时,我们可以看到,50%的站点需要 14 秒才能取得交互。这些网站光是用来解析和编译 JS 的时间就长达 4 秒。

考虑到获取和处理 JS 和其他资源所耗费的时间,也就不奇怪用户可能需要在页面可用之前等待一段时间了。我们绝对可以在这个方面做的更好。

从网页中删除不必要的 JavaScript 可以减少传输时间、CPU 密集型解析和编译以及潜在的内存消耗,同时也有助于加快网页的交互速度。

执行时间

不光是解析和编译会有时间成本。执行 JavaScript(在解析 / 编译之后运行代码)也是需要在主线程上进行的操作之一。长的执行时间也会延迟用户与你网站的交互时间。

如果脚本执行的时间超过了 50ms,那么延迟交互的时间将会是下载、编译和执行 JS 所需时间的总和——Alex Russell

为了解决这个问题,可以将 JavaScript 脚本分为几个小块来执行,以避免锁定主线程。探索一下是否可以减少脚本执行过程中进行中工作量的可能性。

减少 JavaScript 交付成本的模式

当你试图降低 JavaScript 解析 / 编译和网络传输所用时间时,类似于基于路由分块和 PRPL 这些模式也会有用。

PRPL 是一种通过激进的(aggresive)代码分割和缓存来优化交互性的模式:

为了能将PRPL 的影响以视觉化方式表现出来。

我们用V8 引擎中的Runtime Call Stats 分析了流行移动网站和progressive Web Apps(PWA)的加载时间。正如我们所看到的,解析部分(用橙色表示)是很多网站页面加载时产生显著时间消耗的部分。

Wego 网站就使用了 PRPL 来保持较低的路由解析时间,让页面交互得以快速的进行。以上的很多站点都试图采用代码分割和性能预算来降低 JS 的消耗。

JavaScript 的其他消耗

JavaScript 还可以通过其他方式来影响页面性能:

  • 存储。页面可能会因为垃圾回收(GC,garbage colleciton),页面可能会出现画面中断卡顿(junk)和暂停。因为当一个浏览器回收内存的时候,JS 的执行也会被中止,所以经常回收垃圾的浏览器会比我们想象中的更频繁地中止 JS 的执行。在这种情况下,可以通过避免内存溢出和频繁内存回收来保持页面的流畅。
  • 在运行时,长时间的运行 JavaScript 会阻塞主线程,导致页面没有响应。这种情况下,可以将脚本的工作量分成多个小的板块(具体可用 requestAnimationFrame() 或者 requestIdleCallback() 进行任务调度)来执行,以此减少页面响应的问题。

Progressive Bootstrapping

很多网站将优化内容可视性作为保证交互性所需代价的一部分。为了在 JavaScript 有大体积包体时改善首屏性能,开发人员有时会先用服务器端渲染帮助客户提前看到页面内容,然后再在 JavaScript 最终执行完成后“升级”附加上事件处理程序。

但是值得注意的是,这样做也是有代价的。你 1)通常会发送一个更大的 HTML 响应来增加交互性,2)在一段时间内,用户会处在一半的页面交互体验缺失的奇怪状况下,直到 JavaScript 处理完成。

Progressive Bootstrapping 或许会是一个更好的处理方式。浏览器请求一个最少化的功能页面(仅由当前路由所需要的 HTML/JS/CSS 组成)。当有更多的资源请求的时候,应用程序则可以懒加载(lazy-load)和解锁更多的功能。


Progressive Bootstrapping visual by Paul Lewis

仅加载可视区域内的代码是其中的关键。PRPL 和 Progressive Bootstrapping 模式均可以用来实现这一点。

结论

传输脚本的大小对低端网络至关重要,而解析时间对于 CPU 有局限性的设备很重要。降低传输脚本的大小和减少解析消耗时间是有必要的。

有团队发现采用严格的性能预算可以成功降低他们 JavaScript 的传输和解析 / 编译的时间消耗。具体可参照 Alex Russell 的“ Can You Afford It?: Real-world Web Performance Budgets ” 一文中关于移动设备预算的指导。


(考虑一下在我们所做的架构决策下,JS 有多大的空间可以让我们的应用程序具有逻辑)

如果你正在建一个用于移动设备上的站点,请尽可能的在代表性硬件上开发,保持较低的 JavaScript 解析 / 编译的时间成本,并采用性能预算来确保团队对自身 JavaScript 的成本关注。

更多相关学习


(点击观看视频,作者 2017 年在 Chrome Dev Summit 上的演讲,其中涵盖了本文内容,其后就 Pinterest 和 Tinder 这样的制作网站进行了性能案例研究

作者感谢了来自 Nolan Lawson,Kristofer Baxter 和 Jeremy Wagner 的反馈。

原文链接: The Cost Of JavaScript

感谢徐川对本文的审校。

公众号推荐:

2024 年 1 月,InfoQ 研究中心重磅发布《大语言模型综合能力测评报告 2024》,揭示了 10 个大模型在语义理解、文学创作、知识问答等领域的卓越表现。ChatGPT-4、文心一言等领先模型在编程、逻辑推理等方面展现出惊人的进步,预示着大模型将在 2024 年迎来更广泛的应用和创新。关注公众号「AI 前线」,回复「大模型报告」免费获取电子版研究报告。

AI 前线公众号
2018-01-02 17:313551

评论

发布
暂无评论
发现更多内容

week3课题作业

一个典型的大型互联网应用系统使用了哪些技术方案和手段

史慧君

架构师训练营总结 -4

River Tree

学习 极客大学架构师训练营

【极客大学】【架构师训练营】【第四周】学习总结

NieXY

极客大学架构师训练营

想解耦必分层

菜根老谭

程序员 架构思维 分层思维

如何做互联网系统架构

dapaul

极客大学架构师训练营

week04总结

seki

架构师训练营第四周作业

zongbin

极客大学架构师训练营

系统架构知识总结

史慧君

架构师训练营 第四周 学习总结

亮灯

第四周总结

安阳

架构师训练营 0 期第四周

Blink

大型互联网系统技术总结

dapaul

极客大学架构师训练营

【第四周】命题作业——大型互联网系统的技术解决方案和手段

三尾鱼

极客大学架构师训练营

大型网站技术架构--概述

wei

第四周-命题作业

天之彼方

架构师训练营第四周学习总结

赵凯

互联网架构设计

Homework- 典型的大型互联网应用系统

River Tree

Homework 大型互联网应用系统

第四周作业

安阳

大型互联网应用系统使用技术方案和手段

wei

架构师训练营第 4 周 _ 学习总结

方舟勇士

课程总结

Redis系列(四):天天用着Redis集群,主从同步该知道吧?集群工作原理是否需要了解下?

z小赵

Java redis 高并发 高并发系统设计

第四周学习总结

天之彼方

架构师训练营第四周课后作业

赵凯

高并发 高并发系统设计

week04作业

seki

架构师训练营第四周总结+作业

林毋梦

架构师训练营第 4周 _ 课后作业

方舟勇士

课程作业

架构师训练营第四周总结

Geek_2dfa9a

架构师训练营第四周作业

Geek_2dfa9a

关于系统架构学习总结

imicode

架构师训练营第4周作业

aoeiuvzcs

JavaScript的成本_JavaScript_Addy Osmani_InfoQ精选文章