你是说一个只读属性正在破坏我的性能?

Hacker News Top 新闻

摘要

本文解释了只读属性`scrollHeight`如何通过触发Chromium中的同步布局更新而导致性能问题,并建议使用一个大数值而不是频繁重新计算scrollHeight。

暂无内容
查看原文
查看缓存全文

缓存时间: 2026/07/13 07:55

# 你告诉我一个只读属性居然拖垮了性能? 来源:https://shub.club/writings/2026/july/check-your-scrollheight 发布于 2026 年 7 月 9 日 • 93 次浏览 最近我在深入排查 Letta Desktop 的性能问题;剧情老掉牙——用得越久,产品越慢。这看起来很明显,大概就是某个长时间运行的 for 循环,或者未优化的代码。 但我后来才意识到,实际上问题跟我的代码无关(好吧,其实也有关,但根源在于一个错误的假设)。问题出在我强制 UI 在有新消息时自动滚动到底部的方式上。 你看,我之前用的是这么个简单的脚本: `` el.scrollTop = el.scrollHeight; `` 看起来很合理,应该不会影响性能吧? 如果你去看 scrollHeight 的规范,这个属性似乎是静态的,只有在绘制时才会更新,而不是在访问时动态计算。 当然是我错了,这玩意儿根本不高性能。为什么要每次元素被修改时都去计算这个属性呢?更合理的做法是等用户请求时再计算。 问题就在这里:新消息到来时 scrollHeight 总会变化,如果大量消息源源不断地涌入,并且我们需要持续滚动到底部,那速度自然就慢了。 `` int Element::scrollHeight() { if (!InActiveDocument()) return 0; GetDocument().UpdateStyleAndLayoutForNode(this); if (GetDocument().ScrollingElementNoLayout() == this) { if (GetDocument().View()) { return AdjustForAbsoluteZoom::AdjustInt( GetDocument().View()->LayoutViewport()->ContentsSize().Height(), GetDocument().GetFrame()->PageZoomFactor()); } return 0; } if (LayoutBox* box = GetLayoutBox()) { return AdjustForAbsoluteZoom::AdjustInt(box->PixelSnappedScrollHeight(), box); } return 0; } `` (这是 Chromium 中 scrollHeight 的实现,源码在此 (https://chromium.googlesource.com/chromium/src/+/0d4083da3bbd88b97fd0df58d5c4ab5732a2f08c/third_party/blink/renderer/core/dom/element.cc)) 现在想来,如果当初反过来实现,估计也会有同样的问题吧。但对我来说,我不过是默认以为只读属性通常都是很高性能的。 所以真正的建议其实很简单: 属性可以是动态的,尤其是那种一看就知道会随事件变化而变化的属性。 至于滚动问题的解决方案:我只是用一个非常大的数字来代替精确计算 scrollHeight,反正浏览器最终会限制到边界值。

相似文章

不要自己造轮子…

Lobsters Hottest

作者将“不要自己造轮子”的原则扩展到Web开发领域,反对自定义实现滚动、链接导航、文本选择等浏览器原生行为。

作为陷阱的<noscript>元素

Lobsters Hottest

本文讨论了<noscript>HTML元素的局限性:它仅在JavaScript完全禁用时提供后备内容,而不会在JavaScript因其他原因失败时提供。文章建议改用DOM API动态更新内容。

CSS原生视差效果

Hacker News Top

使用滚动驱动动画时间线的CSS原生视差效果,提供了一个高性能且简单的工具类,无需JavaScript。

页面重量至关重要

Lobsters Hottest

呼吁通过减少页面重量、避免沉重的JavaScript框架、跟踪和广告,来构建更简单、更快速的网站。作者主张回归静态HTML和CSS,以尊重用户的时间和资源。

为变更优化,而非应用性能

Hacker News Top

本文指出,软件团队常常过度优化微性能基准测试,却牺牲了开发者体验和工程吞吐量,而这两者才是长期交付速度与可维护性的真正瓶颈。