Ember.js: 2.X和3.X版本之间的性能损失

创建于 2020-05-14  ·  28评论  ·  资料来源: emberjs/ember.js

版本2.X和3.X之间有60%的性能损失。 请参阅下面各种版本的小提琴中的渲染时间日志。 简化示例以演示纯渲染性能,而无需任何样式和计算。

2.18提琴渲染时间:〜500ms
3.18小提琴渲染时间:〜800ms

Bug Regression Rendering

最有用的评论

只是想对此进行快速更新:

我们跑了类似@runspired建立与一个TracerBench测试emberobserver.com ,这是我们常用的测试应用程序之一,看看是否有任何蛙沸点所发生的不显着的版本(如小的性能变化是版本,但总结起来有很大的变化)。 这是该测试的结果:

ember-observer-2.18-3.18.pdf

从这些结果可以看出,存在两个相当确定的跳跃:

  1. 灰烬3.0至灰烬3.1
  2. 灰烬3.16至灰烬3.17

3.17中的回归是由于Glimmer VM升级而引起的,我们目前正在集中精力减少它,因为它是最近才出现的,很可能会开始影响即将在LTS周期更新的应用程序。

经过与核心团队的讨论,当时实际上已经知道3.1中的回归。 这部分是由于启用了本地getter并使用了Object.defineProperty 。 它被认为是可以接受的回归,以允许该框架继续使用更新的浏览器功能。

通常,在本期开始时提出的{{each}}情形似乎比emberobserver.com回归的方式更多,且方式也不同。 一旦我们深入研究了3.17回归,我们将专注于优化{{each}}来查看总体上可以改进的地方。

感谢大家的耐心配合!

所有28条评论

在计算机上的Chrome 81中运行了几次之后,我得到了:

2.18最佳时间:283ms
3.18最佳时间:471ms

在关闭DevTools的情况下运行它。

然后我通过以下方式将3.18旋转项转换为Ember Octane:

  • 对组件和控制器使用本机类。
  • 使用@tracked而不使用@computed
  • t-r组件转换为仅模板的组件,因为它不需要后备类。
  • 调用组件时使用尖括号语法。
  • 在模板中的适当位置使用命名的args和this.

在那之后,我从3.18.1得到的最佳时间是276ms,因此与2.18值相当,这是有意义的改进。

这些性能测试并不是特别科学,而且我还没有研究哪种更改对性能最重要。

在旋转中进行概要分析很容易出错,我们可以移植到普通的ember-cli应用程序仓库(使用两个版本的每个分支)进行分析吗?

@rwjblue我在普通的ember-cli应用程序上得到的结果相同。 可以在这里测试

@ richard-viney可能需要改进,但问题是两个版本中都没有弃用的代码,并且出现性能损失似乎是不可接受的。

  • 使用仅模板组件可能会导致性能提高,但是tr绝对肯定需要支持类来计算某些内部样式。 示例已简化以演示该问题。
  • 通过所有重构,您将获得2.8%(283ms-> 276ms)的性能提升,而同期2.18 考虑将现有的2.18应用程序升级到3.X。 仅仅重构所有组件以获得2%的提升绝对是不可行的。

@barisnisanci同意,我的意思并不是要建议这种重构是必要的,以避免在升级时出现明显的性能下降。 这是一个实验,以查看使用现代约定是否会产生任何影响,因为这可能有助于隔离问题和/或在需要时予以解决。

通过测试中间的LTS版本(即3.4、3.8、3.12和3.16)来了解哪个Ember版本引入了性能下降将是很有趣的。

@barisnisanci Ember Twiddle和ember serve默认在开发模式下运行。 在开发过程中,启用了许多额外的工具,这些工具会严重降低性能。 我们通常不会将其视为回归或问题,除非它的影响足以影响开发人员的人机工程学。 所以首先,我将再次检查您是否在生产模式下同时运行两个版本。

我下载了您的示例,并在生产模式下同时提供了2.8和3.18。 我发现的是,看来您可能是正确的,平均而言,两个助手操作之间的时间间隔(此处正在测量)在3.18中似乎比在2.8中要大。 这是基于我在没有很多控件的情况下在我的工作笔记本电脑上采集了一些样本,因此很难确定,但是直视它,可能会稍有变化。

但是,查看其他更有意义的指标,我没有看到任何变化。 专门查看呈现内容的总时间,它们的外观大致相同。 例如,首次绘画的时间大致相同。

Screen Shot 2020-05-18 at 11 10 15 AM

重要的是要记住,我们有很多工作分散在很多地方,并且当我们进行更改时,有时工作会四处走动,但不会影响_overall_指标。 这就是为什么我们使用TracerBench检查性能变化的原因,因为它旨在考虑渲染的整个阶段并考虑_macro_级别而不是_micro_级别的所有更改,例如助手之间的运行时间。

我们可能应该尝试在更长的时间内尽快进行TracerBench测试,只是为了验证这些发现并确保我们总体上没有下滑(我们通常将其用于较小的变化中,因为我们期望潜在的回归)。 我们还应该尝试使其定期运行,以便可以看到趋势线。

@pzuraq刚刚用rowsCount:300columnsCount:20差异更新了存储库,现在应该更加明显。 两者都以--environment production

  • 3.18第一次绘画:3489毫秒
    3 18
  • 2.18第一次绘画:2814毫秒
    2 18

还注意到JS Heap从未在3.18中发布,但可能对GC不利。

我可以在组件上添加样式绑定,服务注入,更繁重的计算,而不是增加数量,但是它们可能掩盖了潜在的问题。

就像您提到的那样,总体指标比微小的变化更重要。 但是,在我们的案例中,微小的差异会导致性能大幅下降。 在升级到3.18后,我们的商业应用程序的初始渲染时间从15秒增加到20秒。 希望您会考虑以百分比表示的回归,而不是轻微的毫秒变化。

我们公司正遭受这个问题的困扰。 我们将灰烬版本从2.18更新到3.16。 然后我们的渲染时间超过了“ 50”%。 当我们使用复杂的结构时,渲染时间之间的差异变得更加明显,而不是轻微的毫秒变化。 关于此问题有任何更新吗? 我们的基准测试显示渲染时间增加了50%。 决定暂时维持在2.18。 如果需要进行重大重构,我们可以考虑更换框架。

@ Caglayan06您能否确认正在使用生产标志? 只是要确保数字是苹果对苹果!

@ Caglayan06-这不可能是一件事。 @barisnisanci提供的复制可能与您的应用程序配置文件显示的内容不匹配。 您能否在您的应用程序中复制一般性问题(或从上方确认@barisnisanci的示例存储库代表您的使用场景/配置文件输出)?

您对此线程中@barisnisanci的最新帖子有何评论?
将2.18升级到3.16后,我们遇到了类似的性能问题。 我们有40%的性能损失。 我们将评级下调至3.12,但仅挽救了20%的亏损,但仍不及2.18。 重构您之前提到的方式所花费的时间几乎与切换框架一样。 我们应该在这个问题上采取任何行动吗?

最近我们升级到了余烬3.16.8,我们没有perf测试用例,并且暂时没有发现明显的性能问题。
但我希望尽快解决并解决性能问题。
>

PS:ie11中使用了更多的内存和cpu。 有时会导致ie11崩溃。

@ Caglayan06-这不可能是一件事。 @barisnisanci提供的复制可能与您的应用程序配置文件显示的内容不匹配。 您能否在您的应用程序中复制一般性问题(或从上方确认@barisnisanci的示例存储库代表您的使用场景/配置文件输出)?

@rwjblue @barisnisanci的示例对我来说@barisnisanci的用法相同。

@ Caglayan06您能否确认正在使用生产标志? 只是要确保数字是苹果对苹果!

@scottmessinger是的,我们正在运行生产标志。 我们的结果与@barisnisanci的结果相似。

我们改进了代码结构。 它提高了性能,但仍不如ember 2.18版本快。 如果我们在2.18中进行更改,我们将获得最佳结果。

我们无法检修我们的代码系统以更改3.16代码语法和新功能。 这对我们来说太昂贵了,因为我们的项目很大。 重构所有项目可能比更改框架要花费更多。 是否会对此问题采取任何措施?

是否会对此问题采取任何措施?

当然是! 我们只需要花时间分析和弄清楚发生了什么。 但这实际上不需要等待任何人,但您需要挖掘😸

@rwjblue @barisnisanci的示例对我来说@barisnisanci的用法相同。

@ Caglayan06-嗯,那不是我真正问的。 我知道@barisnisanci的示例有效,我要求您对其进行查看/分析/将性能特征与您的应用程序进行比较,并查看该示例有效(且较慢)的_way_是否与您的应用程序匹配。

@ Caglayan06-嗯,那不是我真正问的。 我知道@barisnisanci的示例有效,我要求您对其进行查看/分析/将性能特征与您的应用程序进行比较,并查看该示例有效(且较慢)的_way_是否与您的应用程序匹配。

@rwjblue我将@barisnisanci的回购集成到我们的应用程序中,它给出了相似的结果。 当我们将版本从3.16更改为3.12时,我们的性能得到了提高。
但仍不如2.18版本快。

在我们的应用程序中的一些示例:
2977

结果是:
甚至我们改进了代码结构,平均总渲染时间;
2.18渲染时间:1x秒
3.16渲染时间:1.6x秒。
3.12渲染时间:1.4x秒。

3.20进行了VM升级,所以我想知道这是否有帮助

@NullVoxPopuli使用3.20.0-beta.2 FP没有运气:3.4秒(与3.18相同)

由于3.12显示了更好的结果,我认为自动跟踪可能会引入该问题。 考虑到@ Caglayan06的3.12-> 3.16基准测试中整个应用程序性能下降,#18225也可能与之相关。

嗯我想知道反向兼容的东西有多少开销

一些一般性问题:

  • 异步观察者可选功能标志的值是什么?
  • 有问题的应用是否使用QP?
  • 负速度会影响所有路线还是仅影响某些路线?

一些一般性问题:

  • 异步观察者可选功能标志的值是什么?
  • 有问题的应用是否使用QP?
  • 负速度会影响所有路线还是仅影响某些路线?

@rwjblue

  1. 不使用异步观察者标志,我认为在3.12上默认为false。 在3.16上进行测试并没有太大区别。
  2. 在主要路线上广泛使用的QP。 但是,即使没有任何性能也会观察到性能下降。
  3. 所有路线均受影响

同样,示例存储库未使用以上任何内容,但在3.X中仍然较慢。 在每个次要版本中,渲染时间可能会逐渐增加,因此我们无法查明确切的问题。

Tracerbench报告显示,在这种情况下,2.18至3.18的确减少了约17%,但是如果完成了向微光分量的转换,则改善了而不是减少了约18%。

2.18至3.18没有其他更改
2.18至3.18 +辛烷+微光组件

我为此准备了一个自己的分支,为此我添加了一个自动运行器,并且正在努力改进运行器,以便我们可以根据版本/提交迅速缩小范围,以查找回归发生的位置。 https://github.com/runspired/version-performance/runs/801596557

非常感谢@runspired设置了这些测试! 现在,我们有了可靠的方法来可靠地测量回归,我们可以迭代解决这些问题。

就上下文而言, @ krisselden开发了TracerBench作为专门用于以全面方式测试性能的工具,并且我们一直在内部将其用于主要重构,例如装饰器自动跟踪/修订跟踪。 在LinkedIn上,我们使用它在每次Ember升级之前测试我们的应用程序,而且还没有看到这种回归水平。

但是,这肯定是我们错过的东西。 最后,我们将测试具有特定用例和行为的特定应用。 这可能是我们没有发现的问题,因为我们的测试用例应用程序未使用回归的功能,例如@barisnisanci的复制。 即使我们解决了该复制中的问题,也可能无法解决其他问题,因此,如果您遇到回归问题,我们肯定会喜欢您的用例复制。 我们将努力使TracerBench设置更易于使用,以便您可以在本地进行测试并提交类似@runspired的副本

我们将深入研究确切的问题并找出解决方案。 最重要的是,即使我们看到使用Octane加快了速度,_any_ API也不接受这种级别的回归。 如果用户无法升级和逐步升级,那么我们就不会一起爬山。

请继续关注更多更新,我们会在解决问题时通知您!

非常感谢@runspired的出色酷炫https://github.com/TracerBench/tracerbench-compare-action

只是想对此进行快速更新:

我们跑了类似@runspired建立与一个TracerBench测试emberobserver.com ,这是我们常用的测试应用程序之一,看看是否有任何蛙沸点所发生的不显着的版本(如小的性能变化是版本,但总结起来有很大的变化)。 这是该测试的结果:

ember-observer-2.18-3.18.pdf

从这些结果可以看出,存在两个相当确定的跳跃:

  1. 灰烬3.0至灰烬3.1
  2. 灰烬3.16至灰烬3.17

3.17中的回归是由于Glimmer VM升级而引起的,我们目前正在集中精力减少它,因为它是最近才出现的,很可能会开始影响即将在LTS周期更新的应用程序。

经过与核心团队的讨论,当时实际上已经知道3.1中的回归。 这部分是由于启用了本地getter并使用了Object.defineProperty 。 它被认为是可以接受的回归,以允许该框架继续使用更新的浏览器功能。

通常,在本期开始时提出的{{each}}情形似乎比emberobserver.com回归的方式更多,且方式也不同。 一旦我们深入研究了3.17回归,我们将专注于优化{{each}}来查看总体上可以改进的地方。

感谢大家的耐心配合!

我们可以获取有关此问题的最新信息吗? 大约两个月了。

是! 已经过去了两个多月,我们一直在努力解决这个问题,并继续在Glimmer VM中进行重构,这样做确实很不错。

如前所述,我们专注于两套独立的修复程序:

  1. 针对尝试升级到下一个LTS的人们,低风险重构可在3.20 LTS版本中发布
  2. 较大规模的重构可以落入主平台,以长期提高性能

对于第一组修复程序,我们重构了相当数量的经典Ember代码,因为它是受影响最大的代码。 根据LinkedIn内部应用程序中的测试,我们可以通过这种方式将整体性能损失从3.16-3.20降低到统计上无关紧要的数量。 不幸的是,我没有机会对Ember Observer进行测试,但我认为这将是一个类似的结果,因为它们通常会紧密地跟踪在一起。

对于第二组修复程序,我们相对较新,因为它们很大,其中包括:

  • 将VM更新为完全基于内部自动跟踪,摆脱多余的标签
  • 重构VM以使用单个单态引用类,而不是使用许多复杂性很高的实现
  • 删除未使用的AoT编译模式

结果非常棒!

结果.pdf

这是将当前Ember母版与Ember 2.18进行了比较,并复制了@barisnisanci的上述内容。 现在,如前所述,这是一个非常具体的用例的基准,该用例也过于简单。 我们确实没有看到我们的任何实际应用基准测试都取得了如此显着的进步,但总体而言却要适度得多。 希望这对@barisnisanci和其他人的应用程序有帮助,我们一定很来信

已在余烬主分支上测试过回购。 Still First Paint:(3035.7 ms)似乎大于2.18(2752.3 ms)

还使用不同版本的余烬在我们的产品上进行了测试。 主分支似乎比我们的应用程序中的3.12慢%25至%40。 根据以下结果,如果不进行重大重构,我们将无法升级ember。

perf

@barisnisanci对不起,事实似乎是如此! 正如我之前在本主题中提到的那样,我们将需要以统计上合理的方式重现这些结果,以便能够A.确认问题,并B.寻求改进和总体上更好的解决方案。 我建议您将TracerBench添加到您的应用程序中,以便您可以自己运行这些基准测试,或者进行另一次复制,以在master上演示问题。

此页面是否有帮助?
0 / 5 - 0 等级