【译】为什么硬件速度越来越快,而我们使用的应用程序却越来越慢?

Nov 18·11 min
AI 生成的摘要
现代硬件虽快,但应用性能滞后,揭示了技术进步与用户体验间的鸿沟。Web技术虽灵活,但性能代价显著。Electron等工具虽便捷,却常导致资源浪费。原生应用体验佳,但开发复杂。性能优化需重视,以提升用户体验。
Photo by Claude Sonnet 3.5

这是一个关于"法拉利被迫运货"的现代寓言。硬件工程师们夜以继日地在研发超级跑车,软件工程师们则孜孜不倦地在装载大象。结果就是:一台能飞上月球的电脑,被用来运行一个会卡顿的记事本。

看看这些经典场景: 32GB内存的电脑打开浏览器,风扇呼呼直转 八核处理器的手机刷朋友圈,发烫得像个暖手宝 光速级的固态硬盘,等待软件加载时像在读纸质书 价值上万的旗舰机,运行App时比十年前的功能机还慢

这就像是:

  • 请了个博士生来端茶倒水
  • 买了辆法拉利来送快递
  • 用航母来钓鱼
  • 让火箭去送外卖

最讽刺的是:

  • 内存越大,软件占用越大
  • CPU越快,后台进程越多
  • 屏幕越大,广告越大
  • 网速越快,预加载的垃圾越多

现代硬件快得令人难以置信。笔者正在使用的 M1 Max 运行频率为 3.2GHz,意味着每秒有 32 亿个时钟周期。然而,Microsoft Teams 打开一个链接需要 3 秒钟,我拒绝相信这需要 96 亿个时钟周期。这显然是一个过度简化的说法,但核心观点依然成立:硬件越来越快,但我们使用的应用程序却越来越慢。

"这是因为我们现在做的事情更多了。" —— 这是一个后期资本主义拥护者的说法。让我来解释一下。

现代计算能力的一个绝佳例子是电子游戏。在普通消费级硬件上,我们可以实时模拟包含物理引擎和光线追踪的大型 3D 环境,还能和其他地区的朋友一起玩,同时每秒处理 1.24 亿像素1

从另一个角度来看,人们已经成功在各种具备计算能力的设备上运行 DOOM 游戏:计算器、iPod、相机等。这些低功耗、几乎可以说是一次性的设备,仍然有足够的计算能力来运行 1993 年最先进的游戏。考虑到已经过去了三十年,这并不特别令人惊讶,但它展示了我们在技术上取得的进步。

"Web 技术很糟糕"

Web 技术很酷。实际上,Web 技术在向后兼容性、跨平台性和易用性方面都独树一帜。Web 还有一个事件驱动模型,使得 UI 编写变得更加容易。当然,这些便利是有代价的:速度。执行像 JavaScript 这样灵活的语言本身就很困难,当比较快速的原生应用和缓慢的基于 Web 的应用时,这通常是首要被指责的对象。毕竟,解释型的动态类型语言必然会消耗更多内存并且运行更慢。

根据具体场景,JavaScript 可能确实应该背这个锅。例如,webpack 需要解析数千个文件、构建抽象语法树(AST),还要做一些我不太理解的 CPU 密集型操作,所以 esbuild(Go)和 swc(Rust)在这方面比 webpack 快得多是很合理的。

但对于一般的 Web 应用来说,并非如此;Web 技术并不是导致你那个华而不实的 IRC 聊天应用运行帧率只有 5FPS 的原因。几周前 Twitter 上流传的一个例子是 McMaster-Carr 的产品目录网站。通过积极的预加载和服务端渲染,他们让网站在使用和导航时感觉非常流畅,而这仅仅使用了几十年前的技术(ASP.NET、jQuery)。那些盲目追随新技术的人傻眼了。

如果你是 React 的反对者,这可能看起来是一个反对 React 和其他"现代" JavaScript 框架的好论据,但这完全2是错误的理解。看看 NextFaster(代码仓库)就知道了,用 Next.js 构建并部署在 Vercel 上的 McMaster 目录克隆版本,速度同样快,甚至更快。

Figma 可能是 Web 技术的巅峰之作。一个以 60FPS 运行并支持实时多人协作的完整设计工具,仔细想想真的很疯狂。诚然,它并不完全是 JavaScript 实现的;应用的大部分功能都运行在 WebAssembly 和 WebGL 上。他们是否能通过原生应用获得更好的性能?可能吧。但这也意味着要放弃作为网站随时可访问的便利性。相反,他们全力投入优化,证明了浏览器确实能够达到惊人的性能。

附注:向 V8、SpiderMonkey 和 JavaScriptCore 的开发者们致敬,正是因为你们的神奇工作,我们其他人才能构建任何东西。

"Electron 很糟糕"

注:这里的"Electron"泛指 Electron、CEF、WKWebView、Edge WebView2 和任何其他 Web 到原生的封装工具。

Electron 让 Web 应用可以作为桌面应用部署。这种吸引力是不可否认的。现在,你可以雇佣一个技术栈的开发者,构建一次应用,然后为所有架构和操作系统(是的,包括 Linux)提供"桌面"应用。

代价是什么?运行 Web 应用最可靠的方式就是使用网页浏览器,所以 Electron 干脆...把浏览器打包进去了。能出什么问题呢?¯\_(ツ)_/¯

事实证明,问题多得很。在过去十年里,应用下载体积超过 500MB 已经变得司空见惯,它们消耗大量的内存和 CPU 资源,逐渐耗尽你的电池。而且即使消耗了这么多资源,使用体验也并不好。很多应用都通过奇怪的滚动和选择行为、外观和导航处理暴露出它们非原生的本质,更不用说切换界面时令人沮丧的迟钝感。Discord 和 Teams 就是这种 Electron 化的典型例子。它们都有不错的移动应用,外观和使用感都很好,但桌面端却只是一个重新包装的网站。为什么?

这其实不能完全怪 Electron。Electron 只是说:"这里有一种方法可以把你的 Web 应用放在一个窗口里"。

真正的责任在于开发这些应用的公司。构建优秀的 Electron 应用是完全可能的 - Slack、Obsidian 和 Notion 就是很好的例子。你只需要真正在意它。

说到 Electron,不得不提到 Brackets、Atom,以及更出名的 VS Code。考虑到在 JavaScript 中编辑大文件就像是在射中自己的脚后还要跑马拉松:虽然证明了某个观点,但我不确定是哪个观点。说实话,VS Code 能运行得这么好已经很令人印象深刻了。

不可否认,VS Code 的成功很大程度上应该归功于其插件生态系统,而这在很大程度上要归功于 Web 技术栈的易用性。最近我为 SWC 写了一个(玩笑性质的)插件,我可以自信地说,原生插件的开发体验远不及 Web 那种超快的迭代周期。

"原生应用很糟糕"

所有这些对 Web 技术的贬低可能会让你认为我喜欢使用原生应用。大多数原生应用的使用体验确实很好(比如 Postico、Zed),我经常会在可能的情况下选择使用它们。

在切换到 Zed 几个月后,我觉得我无法回到 VS Code 了。所有操作(真的是所有)都是_瞬间_完成的。你可能觉得 VS Code "够快了",但这就像声速和光速的区别。你几乎感觉不到差异,但这确实带来了天壤之别。Zed 是如何做到的?通过从零开始编写自己的 GPU 框架,并用 Rust 编写整个编辑器。当你真正利用现代硬件时,它_确实_很快。谁能想到呢?

我很想深入研究的一个东西是用于桌面的 React Native。RN 类似 DOM 的渲染模型符合我的 Web 开发思维方式,我认为它在出色的开发体验和性能之间取得了平衡,特别是使用新架构后。目前我还不清楚为什么桌面端的 RN 不太常见,因为从理论上看它似乎是理想的平衡(尽管这可能仅仅是因为缺乏官方支持)。

不幸的是,原生应用领域也并非一片祥和。Adobe 产品以经常崩溃而闻名。Windows 11 的搜索菜单糟糕得令人发笑。macOS 的活动监视器需要 5 秒钟才能显示正在运行的程序列表。

所以我们注定失败了?

显然,这些问题并不局限于特定的编程语言、操作系统或行业。这是一个更广泛的趋势:更快地构建更差的东西。交付优先于质量。

系统资源的滥用

近年来情况变得特别糟糕,因为现代计算机的速度远超普通用户的需求。如果你在桌面浏览器上滚动 YouTube Shorts,它会开始泄露内存(超过 2GB!),直到最终触及资源限制。在过去计算机总内存只有 2GB 的时代,这种情况是不可接受的。现代机器看似充足的计算资源反而成了构建劣质产品的借口。

"够用就行"的心理

显然,我很在意使用体验的流畅度,但通过与不同人交谈,我意识到这种观点并不像你想象的那么普遍。大多数人"能接受"等待 500ms 才出现右键菜单,他们会忽视调整窗口大小时的卡顿重排。这要么是因为人们还记得需要等待 15 秒才能加载一张图片的时代,要么是对糟糕用户体验的习以为常。我们可以做得更好。我们拥有这样的技术。

"先发布再说"文化

快速构建东西。这篇文章并不是在谴责对新想法的快速迭代,但把性能当作技术债务和完全忽视性能之间有着巨大的差异。在我们日常使用的很多东西中,性能似乎连后续考虑的事项都算不上,更像是在等待硬件赶上来。如果你在做一些前沿的东西,这种方法是可以接受的,但如果你的工作只是在屏幕上显示文字,我很难认同这种做法。

表面的性能

读完这篇文章,你可能会认为我建议把所有东西都优化到 CPU 指令级别。虽然这本身很令人印象深刻,但对大多数软件来说是完全不切实际的(除非你是在开发《过山车大亨》的 Chris Sawyer)。这篇文章也不是在谈论为了性能而性能。这只是一个认识:现代大型软件似乎很少关心使用体验,因为反正你都会用。这不是我想要的未来。

如果你是一名软件开发者,我鼓励你精心打造产品。关注毫秒级的细节。欣赏你喜欢使用的东西。为你的工艺感到自豪。

停止用更多资源做更少的事。

Footnotes

  1. 1080p 在 60 FPS 下 = 1920 × 1080 × 60 = 124,416,000
  2. 关于"复杂性之塔"和我们为了在屏幕上显示方框而创建的无限抽象层确实存在争议,但这不是一个有效的性能论据。你几乎可以用任何东西写出高性能的应用。
最后修改时间: Nov 18
cd ..