【问题标题】:Extending JavaScript arrays in V8 and maintaining PACKED kind在 V8 中扩展 JavaScript 数组并维护 PACKED 类型
【发布时间】:2019-07-10 02:10:45
【问题描述】:

我已阅读有关 packed arrays in the V8 engine 的信息,并希望在我的游戏的某些性能关键部分(例如作为粒子的容器)中使用它们。

我想创建一个始终保持 PACKED 的 Array 的自定义子类,但似乎无法用另一个数组扩展 self。

class PackedArray extends Array {
    constructor() {
        super();
    }

    extend(values) {
        // `values` is another array.
        // This obviously won't work, is there another way?
        this = this.concat(values);
    }
}

有没有办法扩展子类数组实例并在 V8 中维护 PACKED 类型?

我知道我可以逐个推送值,甚至可以调用 this.push(...values),但它比 .concat() 慢,并且对于大型数组失败。

【问题讨论】:

  • 你想要推入的预期阵列的大小是多少?我删除了我的答案,因为我没有阅读你的最后一句话^_^。您能否提供一个测试场景,以便我们有一些工作要做?
  • @Icepickle 从几十到几千个元素。
  • @Icepickle 有很多场景,一些例子:用于自定义信号实现的事件接收器列表、游戏内实体列表、可渲染精灵列表等。在游戏中,每个数组应该是尽可能快,因为它们每秒被访问和迭代数千次。
  • @Icepickle 所以我需要一个通用容器,它可以分块分配内存(扩展自身),并且可以在尽可能多的场景中使用。
  • 我是您链接到的 V8 文章的作者。创建PackedArray 子类会将V8 实现细节与您的代码混合在一起,恕我直言,应该避免这种情况。一般来说,专注于编写可读的、惯用的代码。如果您想避免数组中出现漏洞,则无需为其创建子类——只需使用您已经提到的技术即可。请注意,即使HOLEY 元素种类也可以优化,因此根据您的用例,性能差异可能不是什么大问题。您是否衡量过 HOLEYPACKED 对您的代码的影响?

标签: javascript inheritance optimization v8


【解决方案1】:

V8 开发人员在这里。 TL;DR:你可以用“打包元素”做的最好的事情就是不用担心它们。差异几乎无法衡量。

在某些微基准测试中,热核心循环的优化代码中只有少数机器指令,每条指令都很重要,如果“漏洞”检查当前元素是其中之一(实际上是两条: cmp + je on x86),然后跟踪哪些数组不需要它会影响基准分数。但在实际应用中,您对数组元素执行非平凡操作,两条机器指令的影响是不可测量的。您使用自定义包装类所经历的任何扭曲很可能比您可以节省的微不足道的开销更昂贵。


您提出的具体问题可以通过首选“has-a”而不是“is-a”组合来解决:

class PackedArray {
  extend(values) {
    this.#data = this.#data.concat(values);
  }
  get(i) { return this.#data[i]; }

  #data = [];
}

这也将解决使用子类的问题,代码仍然可以使用my_packed_array[10000] = "now you have holes" 来回避.extend() 方法。但是,请记住我在上面写的内容:检查孔的影响是很小,而且这些额外的包装中的任何一个都可能比节省的成本高得多。

编辑:@MathiasBynens 写的也是一个很好的观点:不要为 V8 优化,让 V8 为你优化! :-)

【讨论】:

  • 如果 HOLEY 和 PACKED 之间的差异几乎无法衡量,那么为什么这两种在 V8 中实现?为什么不在 V8 内部坚持使用 HOLEY 并简化代码? Mathias Bynens 在文章中明确表示,存在这种区别是为了提高性能。
  • 几乎永远无法衡量的动机;-)。 -- 我们现在正在更新文章以使其更加清晰。
【解决方案2】:

您可以使用this.splice()修改当前数组。

extend(values) {
    this.splice(this.length, 0, ...values);
}

【讨论】:

  • 这仍然会受到要添加的值数量的限制,不是吗?和this.push( ...values )相比有什么优势吗?
  • 可能类似,我不确定。我不确定为什么它们中的任何一个都会有限制。
  • 这个限制似乎有点大,但这里有一些问题说它大约有 32766 个参数,具体取决于你如何称呼它
猜你喜欢
  • 2013-04-21
  • 2014-03-03
  • 2019-04-01
  • 1970-01-01
  • 2018-06-20
  • 1970-01-01
  • 2011-06-25
  • 1970-01-01
相关资源
最近更新 更多