【问题标题】:Why "Map" manipulation is much slower than "Object" in JavaScript (v8) for integer keys?为什么整数键的“Map”操作比 JavaScript (v8) 中的“Object”慢得多?
【发布时间】:2020-06-12 18:14:55
【问题描述】:

我很高兴使用 Map 在我的 JavaScript 代码库中的任何地方进行索引访问,但我偶然发现了这个基准:https://stackoverflow.com/a/54385459/365104

我也在这里重新创建了它:https://jsben.ch/HOU3g

基准所做的基本上是用 1M 元素填充地图,然后对其进行迭代。

我希望 Map 和 Object 的结果是相同的,但它们有很大的不同 - 有利于 Object。

这是预期的行为吗?可以解释吗?是因为订购要求吗?还是因为 map 正在做一些关键散列?或者仅仅因为 Map 允许任何对象作为键(我希望它使用指针地址作为键,这不需要任何散列)? Map和Object索引算法有什么区别?

这是非常出乎意料和令人沮丧的 - 基本上我将不得不恢复到老式的“对象即地图”编码风格。

更新 #1

根据 cmets 的建议,Object 可能会优化为 Array(因为它是按整数索引的,从零开始)。

将迭代顺序从 size 更改为 0 - 对象仍然是 2x faster。使用字符串作为索引时,Map 的性能提高了 2 倍。

【问题讨论】:

  • 这可能会遇到对象即数组(例如整数索引)优化。将"x" + i 存储为键 - 那么性能要么相同,要么在没有迭代的情况下使用 Map 领先。此外,基准具有不同的输出,一个存储1,另一个存储i;尽管这对整体性能没有影响。
  • tldr;如果使用非整数键(包括不是整数值的字符串),则 Map 一样快或更快。
  • 我希望对象的实现得到超级优化,因为对象是 javascript 的核心,并且涉及从console.log() 调用到Map 的实现(它本身就是一个对象)的所有内容.如果出现某些东西并且比对象更快,我会感到非常惊讶,因为这意味着开发人员可以使用该东西重新实现对象以使对象更快

标签: javascript performance dictionary object v8


【解决方案1】:

(这里是 V8 开发人员。)

我将不得不恢复到老式的“对象即地图”编码风格。

如果这样做,您将成为误导性微基准测试的受害者。

在使用连续整数作为键的非常特殊的情况下,普通的Object 会更快,是的。在那种情况下,没有什么比连续数组更好的了。因此,如果您提到的“代码库中任何地方的索引访问”确实使用了索引集,例如从 0 到 1M 的整数,那么使用 Object 或 Array 是个好主意。但那是个特例。如果索引空间是稀疏的,事情就已经不一样了。

在以随机顺序使用任意字符串的一般情况下,Map 的性能明显优于Object。更重要的是,处理此类对象属性访问的方式(在 V8 中,也很可能在其他引擎中)具有非本地效果:如果一个函数对对象的慢速路径施加过大压力属性查找处理系统,那么这可能会减慢一些 其他 函数的速度,这些函数依赖于相同的慢速路径进行属性访问。

根本原因是引擎针对不同的使用模式优化了不同的东西。引擎可以在底层实现对象和地图几乎相同;但这不是理想的行为,因为不同的使用模式受益于不同的内部表示和实现选择。所以引擎允许你向他们提供一个提示:如果你使用Map,引擎会知道你打算使用这个东西作为地图(呃!),随机键会来来去去。如果您使用Object,那么引擎将(至少在开始时)假定您想要最适合您的普通对象的优化集,其中属性集相当小且是静态的。如果您使用 Array(或仅具有整数属性的 Object,这在 JS 中几乎相同),那么您可以让引擎轻松地为您提供快速的整数索引访问。

使用"x" + i 作为键是一个很好的建议,可以证明微基准测试可以多快被更改,从而产生相反的结果。但这里有一个剧透:如果您(仅)进行此修改,那么您测量的很大一部分将是数字到字符串的转换和字符串内部化,而不是 Map/Object 访问性能本身。

小心微基准;它们具有误导性。您确实必须非常深入地分析它们(通过分析,和/或通过检查生成的代码,和/或通过跟踪其他引擎内部),以确保它们正在衡量您认为的内容重新测量,因此产生的结果告诉你你认为他们在告诉你什么。

一般来说,强烈建议使用代表性测试用例进行性能测量。理想情况下,您的应用程序本身;或者通过将其中的真实部分提取到对真实数据进行操作的测试用例中。而且,如果您无法通过对整个生产应用程序的压力测试来衡量两个实现选择之间的差异,那么这不是值得担心的差异。通过微基准(即几条人工制作的线),我可以“证明”几乎任何不适用于一般情况的东西。

【讨论】:

  • 很高兴知道对于整数有更快的 Map - Object :) 现在我将在 key 为整数的情况下使用 Objects。
猜你喜欢
  • 1970-01-01
  • 2017-11-03
  • 2021-05-21
  • 2015-10-20
  • 1970-01-01
  • 1970-01-01
  • 2017-12-26
  • 2011-01-25
  • 2012-12-20
相关资源
最近更新 更多