- 原文地址:How to write about web performance
- 原文作者:Nolan Lawson
- 译文出自:掘金翻译计划
- 译者:Mancuoj
- 注:原文作者是微软以及Squarespace的前员工,目前效力于Salesforce,也是PouchDB的主要贡献者。
我写关于WEB性能的文章已经很长时间了,我现在已经很擅长去写这些东西了,但有时候回看我以前的博客,我仍然会对我所犯的错误感到害怕。
这篇文章是我试图提炼出多年来我学到的一些东西,作为建议提供给其他有抱负的修补者,benchmarkers,以及任何对测试中浏览器的实际工作感到好奇的人。
为什么要写关于Web性能的文章
第一个问题也是最直观的问题:为什么要写这个?这些不是应该留给浏览器供应商做的事情吗?
在某些方面,是这样的。浏览器供应商知道它们的产品实际的工作流程,如果系统的某些部分运行缓慢,你可以去敲写代码的同事的门问问他们为什么这么慢。(在这个疫情后时代,或者应该给他们发一条私信)
但在其他方面,浏览器供应商不适合坦率地谈论网络性能,毕竟他们的业务就是销售浏览器。网络性能的说法经常被用于市场营销,比如“X浏览器比Y浏览器快25%”,仅这样宣传就需要得到市场营销部门,法律部门的批准,更不用说各种利益相关者了...
而且这还只是在你的浏览器是快的情况下。如果你运行一个基准测试,结果发现你的浏览器是慢的那个,或者是好坏参半的,那么浏览器供应商肯定会对此保持沉默。这就是为什么每当一个浏览器供应商发布一个新的基准测试时,他们的浏览器一定是第一名。因此,当涉及到要准确写出他们的产品的实际工作情况时,浏览器供应商的手会被绑得很紧。
当然,这个规则也有例外。偶尔你会发现某人的个人博客,或者公共错误追踪器上的评论,其中透露出他们的浏览器在某些基准测试中实际上并不那么出色。但是,没有人会不顾一切地宣传他们的浏览器在基准测试中是多么的糟糕。如果有的话,他们会在完成了提高速度的工作之后再谈这个问题,也就是说,这个基准已经经过了几轮的内部讨论,而且可能被用来评估一些提高性能的内部举措 —— 在公众真正听到这个消息之前,这个过程可能会持续数年。
其他时候,浏览器供应商会发布一个新功能,大张旗鼓地宣布,然后含糊其辞地宣称它是如何提高性能的,而不深入研究任何具体细节。不过,如果你真的去研究这些说法,你可能会发现,性能的提高是相当微弱的,或者只在特定的环境中表现出来。(不过,不要指望构建该功能的团队会告诉你这些)
顺便说一句,对于这种情况,我一点也不怪浏览器供应商。我在微软Edge的性能团队工作(早在EdgeHTML时代,在转到Chromium之前),我也做过同样的事情。我写过滚动性能,因为在当时,我们的引擎在滚动方面是最好的。我写了关于输入响应性的文章,是在我们已经让它变得更快之后。(不是之前!绝对不是之前!)我设计了一些基准,明确展示了我们所做的改进。我制作了营销视频,展示我们的浏览器在实验中获胜,而且我们已经知道我们会赢。
如果你认为我在黑微软,我可以轻易地找到其他浏览器供应商做同样事情的例子。但我不会这样做,因为我宁愿黑自己。(如果你在一家浏览器供应商工作,并且正在阅读这篇文章,我相信你肯定会想到一些例子)
不要指望一家汽车公司告诉你他们的竞争对手有更好的里程,更不要指望他们承认他们的新车型安全评级很差劲,这是消费者报告的作用。同样,如果你不在浏览器供应商那里工作(我已经不在了),那么你就有福了,你可以对浏览器说任何你想说的话,并诚实地评估他们的主张,在公平、无偏见的基准中相互比较。
另外,作为一个网络开发者,你可能实际上更有资格编写一个更能代表真实世界代码的基准。浏览器开发人员每天大部分时间都在编写C、C++和Rust,而不是HTML、CSS和JavaScript。因此,他们并不一定熟悉工作中的网络开发人员的日常。
Benchmark的微妙科学
好了,这就是我关于你为什么要费心去写Web性能的长篇大论。那么,你实际上应该如何去做的呢?
首先,我想说的是,在你开始写你的博客之前要先写好基准测试。你的结论和高层次的收获可能会有很大的不同,这取决于基准测试的结果,所以不要假设你已经知道结果是什么。
我过去就犯过这个错误! 有一次,我在写基准之前写了一整篇博文,然后基准完全颠覆了我在文章中要讲的内容。我不得不废掉整篇文章,从头开始。
基准测试是科学,你应该以科学工作的严肃态度对待它。期待同行评审,这意味着最重要的是 公开发表你的基准,并为其他人提供测试指示。相信我,他们会的。在我发表文章后,有一些人通知我,我的基准有一个错误,所以我不得不去纠正结果。(这很烦人也很尴尬,但总比故意散布错误信息要好)
由于你可能最终要多次运行你的基准,甚至多次生成你的图表和表格,所以要尽力简化收集数据的过程,如果某些步骤是手动的,就尝试将其自动化。
我喜欢用Tachometer,它可以自动完成基准测试的许多无聊部分:启动浏览器、进行检测、进行多个检测、进行足够的数量以达到统计学意义,等等。不幸的是,它没有自动生成图表的部分,但我通常会写一些小脚本来输出数据的格式,以便我可以轻松地将其导入电子表格应用程序。
这也引出了一个重要的问题:进行准确的测量。一个常见的错误是使用Date.now(),相反你应该使用performance.now(),因为它会给你一个更精确的时间戳。或者更好的是,使用performance.mark()和performance.measure(),这些也是高精准度的,还有一个好处是你可以在Chrome DevTools中看到你的测量结果。这是个很好的方法,可以反复检查你是否真的在检测你认为要检测的东西。
]
Note: 可悲的是,Firefox和Safari的开发工具仍然没有在其解析器追踪中显示性能标记/检测,IE11多年前就有这个功能。
如上所述,进行多次检测也是一个好主意。基准测试总是会显示差异,如果你只取一个样本,你几乎可以证明任何事情。为了获得最佳效果,我认为至少要进行三次测量,然后计算中位数,或者更好的是,使用像Tachometer这样的工具,它将使用一堆花哨的统计数据来找到理想的样本数。
谦虚
撰写关于网络性能的文章真的很难,所以谦虚是很重要的。浏览器是非常复杂的,所以你必须接受你可能会在某些方面出错。如果你没有错,那么5年后,浏览器更新它们的引擎会使你的结果过时,你也就错了。
不过,有一些方法可以限制你犯错的可能性。以下是一些过去对我来说很有效的策略:
首先,在多个浏览器引擎中进行测试。这是一个很好的方法,可以弄清楚你是否在某个特定的浏览器中发现了一个怪癖,或者关于网络如何工作的一个基本事实。糟糕的是,如果你写了一个基准,其中一个浏览器的表现比其他浏览器差得多,那么恭喜你!你已经发现了一个浏览器的错误。你已经发现了一个浏览器的错误,现在你有一个可重复的测试案例,你可以把它归档到那个浏览器上。
(如果你认为他们不会感谢你,或者不会修复这个问题,那么你就准备好接受惊喜吧。我已经在浏览器上提交了几个这样的bug,他们通常至少会承认这个问题,如果不是在几个版本中直接修复它。有时,当你提出这样的错误时,浏览器的开发者会很感激,因为他们可能已经知道某些东西是个问题,但如果没有来自客户的错误报告,他们就无法说服管理层将其列为优先事项。)
第二,减少变量。如果可能的话,在相同的硬件上进行测试。(对于测试三个主要的浏览器引擎--Blink、Gecko和WebKit--这不幸地意味着你总是在macOS上测试。不要相信Windows/Linux上的WebKit,我发现它的性能与Safari有很大的不同)浏览器可以根据设备是否插电或电池电量不足而有所不同,所以要确保设备已经插上电源并充电。在运行基准测试时,不要运行其他应用程序或浏览器窗口或标签。如果涉及到网络,如果可能的话,使用本地服务器以消除延迟。(或者将服务器配置为总是以特定的延迟进行响应,或者根据需要使用节流。) 在运行测试之前,更新所有的浏览器。
第三,要注意缓存的问题。如果你运行了1000个迭代的东西,结果发现最后的999个迭代都被缓存了,这很容易欺骗自己。JavaScript引擎有JIT编译器,这意味着第一次迭代可能与第二次迭代不同,而第二次迭代又可能与第三次迭代不同,等等。如果你认为你能找出一些低级别的东西,比如"const比let快吗?",你可能做不到,因为JIT会比你聪明。浏览器也有字节码缓存,这意味着第一个页面的加载可能与第二个不同,而第二个甚至可能与第三个不同。(Tachometer通过每次迭代使用一个新的浏览器标签来解决这个问题,这非常聪明)
我想说的是,尽管你努力地做着严格的、科学的基准测试,但你可能只是证明自己是错的。你会发表你的博文,你会为自己感到非常自豪,然后一个浏览器工程师会私下联系你说,"它只在60FPS显示器上这样工作"或者 "只在英特尔CPU上",或者 "只在macOS Big Sur上",又或者 "只有当你的DOM大小超过1000,层深度超过10,并且你使用轨迹球鼠标,而且是星期二,月亮在第七宫的情况下才会这样。"
浏览器的性能有很多变数,你不可能把它们全部抓住。你能做的最好的事情是记录你的方法,解释你的基准测试没有测试什么,并尽量不要做宏大的概括性声明,如 "你应该使用const而不是let,我的基准测试证明它更快" 。你的基准测试充其量证明了,在你非常具体的基准测试中,一个数字比另一个数字高。
结论
撰写关于浏览器性能的文章是很难的,但也不是毫无结果。多年来,我已经取得了足够的成功(我想,也有足够的固执和好奇心),所以我一直在做这件事。
例如,我写过像Rollup这样的捆绑器如何比Webpack这样的捆绑器产生更快的JavaScript文件,而Webpack最终改进了它的实现。我在Firefox和Chrome上提交了一个bug,显示Safari有一个他们没有的优化,而这两个浏览器都修复了它,所以现在这三个浏览器在基准上都很快。我写了一个愚蠢的JavaScript "优化器",V8团队用它来提高他们的性能。
我提出这些例子,与其说是为了吹嘘,不如说是为了说明,只要写出这些东西,就有可能改进它们。在上述所有三个案例中,我实际上在我的基准测试中犯了错误(在某些情况下是非常愚蠢的错误),并且不得不在后来回去修正它。但是,如果你能获得足够的吸引力,并引起正确的人的注意,那么浏览器、捆绑器和框架就可以改变,而不需要你实际写代码去做。(直到今天,我还是不会写一行C、C++或Rust,但我已经影响了浏览器供应商为我写代码,这与我花更多时间玩俄罗斯方块而不是学习新的编程语言的目标相一致)
我写这些的目的是试图说服你(如果你已经读到这里),对你来说写Web性能确实是有价值的,即使你觉得自己并不真正了解浏览器的工作原理,即使你刚刚开始成为一名Web开发者,即使你只是好奇想探究一下浏览器,看看它们是如何运作的。在最坏的情况下,你会犯错(我已经犯过很多次了),而在最好的情况下,你可能会教给别人一些高性能的编程模式,甚至影响生态系统的变化,使事情对每个人都更好。
写关于浏览器性能的文章会有很多好处,而你所需要的只是一个HTML文件和一点耐心。所以,如果你觉得这听起来很有趣,那就开始吧,祝你的基准测试愉快。