【问题标题】:V8 JavaScript Object vs Binary TreeV8 JavaScript 对象与二叉树
【发布时间】:2016-01-24 07:39:58
【问题描述】:

有没有比使用JavaScript Object 更快的方法来搜索JavaScript 中的数据(特别是在V8 通过node.js,但没有c/c++ 模块)?

This may be outdated 但它建议为每个属性动态生成一个新类。这让我想知道二叉树实现是否会更快,但是this does not appear to be the case

二叉树的实现不是很平衡,所以平衡可能会更好(只有前 26 个值是手动大致平衡的。)

有人知道为什么或如何改进它吗?另一方面:动态类的概念是否意味着实际上有大约 260,000 个属性(在第二个链接的 jsperf 基准测试中)以及随后保存在内存中的动态类定义链?

【问题讨论】:

  • 这似乎是一个 XY 问题。你的用例是什么?您是否执行了基准测试来确定普通对象绝对不适用于您的用例?
  • 您确实需要描述一个特定的用例。 “更快的数据搜索方式”并未描述您实际尝试解决的问题。就目前而言,这个问题太不具体了。
  • 用例是在数十万条记录中搜索键。我认为从附加的自定义 jsperf 性能测试中可以看出这一点,以概述差异。

标签: node.js object binary-tree v8


【解决方案1】:

V8 使用“地图”的概念,它描述了对象中数据的布局。

这些映射可以是“快速映射”,它指定从可以找到特定属性的对象开始的固定偏移量,或者它们可以是“字典映射”,它使用哈希表提供查找机制。

每个对象都有一个指向描述它的映射的指针。

通常,对象以快速地图开始。当使用快速映射将属性添加到对象时,映射会转换为描述新属性在对象内的位置的新映射。如有必要,将为对象重新分配足够的空间用于新数据项,并将对象的映射指针设置为新映射。

旧地图保留从它的转换的记录,包括指向新地图的指针和添加导致地图转换的属性的描述。

如果另一个拥有旧地图的对象添加了相同的属性(这很常见,因为相同类型的对象倾向于以相同的方式使用),该对象将只使用新地图 - V8 不会在这种情况下不创建新地图。

但是,一旦属性的数量超过某个阈值(实际上,当前的度量是与使用的存储空间有关,而不是实际的属性数量),对象就会更改为使用字典映射。此时,使用哈希表重写对象。一般来说,它不会再进行任何映射转换 - 添加的任何更多属性只会进入哈希表。

快速映射允许 V8 生成优化代码(使用 Crankshaft),其中对象内属性的偏移量被硬编码到机器代码中。这使得它在可以执行此操作的情况下非常快速 - 它避免了进行任何查找的需要。

显然,生成的机器代码随后依赖于地图 - 如果对象的数据布局发生变化,则必须丢弃代码并在必要时重新优化。 V8 有一个类型分析机制,它收集有关在执行未优化代码期间各种对象的类型的信息。在满足某些稳定性约束之前,它不会触发代码优化 - 其中之一是函数中使用的对象映射不会经常更改。

Here's a more detailed description of how this stuff works.

Here's a video where one of the lead developers of V8 describes stuff like map transitions and lots more.

对于您的特定测试用例,我认为它会在准备循环中添加属性时经历数百次映射转换,然后它最终会转换为基于字典的对象。它肯定不会通过其中的 260,000 个。

关于您关于二叉树的问题:大小合适的哈希表(具有合理的哈希函数和大量对象)对于您只是搜索的用例(作为您的测试)总是优于二叉树代码似乎可以(所有插入都在设置阶段完成)。

【讨论】:

    猜你喜欢
    • 2011-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-07
    • 1970-01-01
    • 2020-02-13
    相关资源
    最近更新 更多