我正在尝试通过这两个 PR 来改进 First Contentful Paint (FCP) 和 Largest Contentful Paint (LCP):
我对这些更改的实际影响非常感兴趣——所以请尝试一下并提供一些反馈。
当然,任何关于测试、重构和测试覆盖率的帮助都非常受欢迎。
我正在尝试通过这两个 PR 来改进 First Contentful Paint (FCP) 和 Largest Contentful Paint (LCP):
我对这些更改的实际影响非常感兴趣——所以请尝试一下并提供一些反馈。
当然,任何关于测试、重构和测试覆盖率的帮助都非常受欢迎。
第一个看起来是一个简单的优化,我认为这是有意义的,@david 和 @eviltrout 花时间优化了这部分,所以我非常想知道他们对此的看法。
第二个感觉长期来看有点脆弱,我完全理解优化的愿望,但这让我有点担心,因为它将是我们以后需要维护的一个区域。
你好 @rrit - 感谢你的 PR。第一个听起来是个不错的改进。你是否能够衡量性能影响?它节省了多少时间?
正如 @sam 所说,第二个的可维护性有点令人担忧。它看起来是从 Ember 源代码复制/粘贴的吗?你是否为了提高性能而更改了某些内容?
现在通过 Map 实现,而不是 Array。
lookupView 在应用程序启动时花费的时间 - 开发实例:
无 patch:124 毫秒
Firefox Profiler (callstack 过滤到 lookupView)
有 patch:9 毫秒
Firefox Profiler (callstack 过滤到 lookupView)
节省的时间:约 115 毫秒
这会将 appendOutletView 内部花费的时间从 1.083 毫秒减少到 946 毫秒 - 开发实例。
是的,实际上是复制粘贴,只有一个更改:使用廉价的 isPath 检查。
// replaces @ember/-internals/utils isPath
// @see: https://github.com/emberjs/ember.js/blob/3537670c14883346e11e841fcb71333384fcbc87/packages/%40ember/-internals/metal/lib/path_cache.ts#L5-L7
// @see: https://github.com/emberjs/ember.js/blob/255a0dd3c7de1187f4a2f61a97cf78bfff8f66a8/packages/%40ember/-internals/glimmer/lib/utils/bindings.ts#L70
let isPath = context.indexOf('.') > -1;
例如,renderTopicListItem 最终会触发许多 _getPath 调用(还可以节省 50-100 毫秒):
Firefox Profiler (renderTopicListItem 内 _getPath 的 callstack 过滤)
也许昂贵的 _getPath 调用应该在 Ember.js 中优化,而不是在 Discourse 中。
并查看 Firefox Profiler 以深入了解 JavaScript 执行:
谢谢您的补丁。第二个补丁似乎有点脆弱。
您的基准测试是在开发模式还是生产模式下运行的?Ember 在这两种模式下的性能差异很大。
@david 找到了一种解决此问题的好方法 - 请参阅他在 github 上的评论。
在 Ember 的“production”构建中,“latest”网页上调用 renderTopicListItem 的时间从 348 毫秒减少到 201 毫秒。
之前的基准测试仍在开发模式下运行。
# 在生产模式下启动 ember
d/ember-cli server --environment="production"
不幸的是,我无法复制这种显著的速度提升。在 Firefox 和 Chrome (macOS) 上,我没有看到任何可衡量的改进。Chrome 在 renderTopicListItem 上花费约 23 毫秒。Firefox 约 30 毫秒。在较旧的 Android 设备 (Pixel 3) 上,我看到约 108 毫秒。更改前后数字似乎没有变化。
顺便说一下,我是通过使用 performance API 来测量这些数字的。我在 renderTopicListItem 的开头添加了 performance.mark("rtli-start"),然后在结尾添加了 performance.measure("rtli", "rtli-start")。
然后,我关闭开发者工具并禁用浏览器插件(开发者工具和浏览器插件会显著影响渲染性能)重新加载浏览器。加载完成后,打开开发者工具并运行此代码来汇总测量结果:
performance.getEntriesByName("rtli").reduce((v, m) => v + m.duration, 0);
我们肯定会合并这项更改——这显然是一个更好的实现。但我不太确定它是否会给我们带来可见的渲染性能差异 ![]()
我仍然可以在 Firefox 的隐私模式(Linux)中使用性能 API 重现性能优势。
正在测试 http://localhost:4200/latest
renderTopicListItem 的耗时从约 290 毫秒降至约 190 毫秒。
我的 Discourse 测试实例包含许多带有许多回复和许多不同作者的主题 - 数据是从生产实例中提取的。这导致需要渲染大量元素。
也许这是我们基准测试的差异所在?
Discourse 在“latest”页面上预渲染 30 个主题。然后内容首次显示(FCP)。视口上方只有约 12 个主题可见。
主题页面也一样:预渲染 20 篇帖子,但视口上方最多只显示 6 篇单行帖子。
这可能是 FCP 的另一个优化点。
您介意分享一下 Firefox 和操作系统版本吗?290 毫秒的数字几乎是 2018 年 Android 设备的 3 倍,这有点令人惊讶。
是的,这也许能解释一些差异。在我的例子中,我使用来自 Meta 的实时数据运行了它们:
bin/ember-cli --environment production --proxy https://meta.discourse.org
是的,这是一个可能的改进。但是,我们需要非常小心,确保布局和/或滚动不会跳动(例如,如果用户在滚动到一半时刷新页面)。“below the fold”的定义也因设备/浏览器/主题而异。
遗憾的是,使用代理运行 ember 对我来说失败了:
d/ember-cli --environment production --proxy https://meta.discourse.org
Discourse Build Error
Error [ERR_TLS_CERT_ALTNAME_INVALID]: 主机名/IP 与证书的 altnames 不匹配:
主机:localhost. 不在证书的 altnames 中:DNS:*.cdck-prod-meta.discourse.cloud
Discourse Build Error
Error [ERR_TLS_CERT_ALTNAME_INVALID]: 主机名/IP 与证书的 altnames 不匹配:
主机:meta.discourse.org. 不在证书的 altnames 中:DNS:*.cdck-prod-meta.discourse.cloud
摘自 Firefox about:support
| 名称 | Firefox |
|---|---|
| 版本 | 95.0.2 |
| Build-ID | 20211219102529 |
| Distributions-ID | canonical-002 |
| 用户代理 | Mozilla/5.0 (X11; Linux x86_64; rv:95.0) Gecko/20100101 Firefox/95.0 |
| 操作系统 | Linux 5.10.0-0.bpo.9-amd64 #1 SMP Debian 5.10.70-1~bpo10+1 (2021-10-10) |
| 操作系统主题 | Adwaita-dark / Adwaita |
| 应用程序文件 | /snap/firefox/777/usr/lib/firefox/firefox |
| 名称 | Firefox Developer Edition |
|---|---|
| 版本 | 96.0b10 |
| Build-ID | 20211228195952 |
| Update-目录 | /opt/firefox-dev-autoinstall |
| Update-通道 | aurora |
| 用户代理 | Mozilla/5.0 (X11; Linux x86_64; rv:96.0) Gecko/20100101 Firefox/96.0 |
| 操作系统 | Linux 5.10.0-0.bpo.9-amd64 #1 SMP Debian 5.10.70-1~bpo10+1 (2021-10-10) |
| 操作系统主题 | Adwaita-dark / Adwaita |
| 应用程序文件 | /opt/firefox-dev-autoinstall/firefox-bin |
摘自 Chromium chrome://system/
| CHROME VERSION | 90.0.4430.212 built on Debian 10.9, running on Debian 10.11 |
|---|---|
| OS VERSION | Linux: 5.10.0-0.bpo.9-amd64 |
操作系统版本:
# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 10 (buster)"
NAME="Debian GNU/Linux"
VERSION_ID="10"
VERSION="10 (buster)"
VERSION_CODENAME=buster
ID=debian
重构的拉取请求现已合并:
感谢你提出这个问题,@rrit - 这是一个很好的改进!
此主题已在 9 小时后自动关闭。不再允许回复。