【问题标题】:Does size of a javascript object/array in affect time to access or change a piece of data in the object?javascript 对象/数组的大小是否会影响访问或更改对象中的一段数据的时间?
【发布时间】:2020-07-13 08:30:04
【问题描述】:

我想知道在大对象/数组中添加或访问数据是否比在小对象/数组中慢。

例如,如果我有一个包含 50000 个项目的对象/数组并想要更改或访问它,它会比只有 500 个项目的较小对象/数组慢吗? 提前致谢!

【问题讨论】:

  • 您可以在恒定时间内访问它。没关系
  • 如果按索引访问,速度是一样的。如果你通过循环访问它,它循环的数据越多,速度就越慢。
  • 是的,理论上处理更大的对象会更慢,但速度太慢了,你不需要关心它。在实践中,将其视为常量。

标签: javascript arrays performance object


【解决方案1】:

访问一个数组元素或对象属性将花费大约相同的时间,无论大小如何。

添加数据会有所不同,具体取决于我们谈论的是数组还是非数组对象,以及添加数据的位置和方式。

我不能谈论任何特定 JavaScript 引擎的细节,但通常可变长度数组实现有两种不同的长度:已分配长度和当前长度。您在 JavaScript 中看到的 array.length 属性是 current 长度,但分配给数组的内存通常大于此长度。例如,一个包含 100 个元素的数组实际上可能会为 128 个元素分配足够的空间。

所以当你调用array.push() 时,数组数据中可能已经有多余的空间了。这个案子非常快。代码只需要增加.length并存储新的数组元素。

这就是为比当前长度更多的元素分配空间的原因:以避免必须在每个 .push() 上重新分配内存。

但是,一旦当前长度达到分配的长度,下一个.push() 需要重新分配整个数组,并且通常必须将所有先前的数组元素复制到新的内存位置。这使得这个特定的.push() 慢得多。但是,随后的.push() 调用会很快,直到当前长度再次达到分配的长度。

在某些情况下,重新分配可能发生在适当的位置 - 可能恰好在数组末尾之后有未分配的空间,因此它可以在不复制的情况下扩展 - 但这种情况不太常见。

这种重新分配的确切策略各不相同:引擎可能会在需要重新分配时立即将分配的数组长度加倍,或者将长度乘以 1.5,或者它选择的任何值。

现在,如果您使用array.unshift() 或array.splice() 在数组的开头 处或附近插入一个或多个元素会怎样?在这种情况下,即使分配的数组长度有空间容纳额外元素,速度也将取决于当前数组长度,因为插入点之后的所有现有元素都必须在内存中移动。

这对于非数组对象来说不是一个因素。添加新属性,无论其键值如何,都不需要移动所有现有属性。对于具有大量属性的对象,它可能会稍微慢一些,但与在数组开头附近添加元素的方式不同。对象是用哈希表或类似的数据结构实现的。当哈希冲突过多(映射到相同哈希值的键)时,引擎可能会决定重新分配哈希表以使其更大,但这将与您添加的任何键值大致相同。键是“小于”还是“大于”任何现有值在这里都无关紧要。

如果您有更具体的问题,我们可以进一步讨论。

【讨论】:

    【解决方案2】:

    如果您需要数组的 final 内容按特定顺序排列,那么 到目前为止 最快的做法是首先组装数组,以任何排序任何内容,然后将数组排序到您需要的最终序列中。

    “排序”在任何现代语言中都是所谓的O(log(n)) 操作,这意味着它的最坏情况性能是“大约”的一些对数元素的数量——“非常好”。如果您随后需要向排序数组添加更多元素,只需将元素添加到末尾,然后重新排序即可。

    注:“已知以某种方式排序的数据集”已经在“计算机出现之前”取得了巨大的成功字面意思打孔卡。

    【讨论】:

    • OP 没有提到任何关于排序或排序的内容,您是要回答不同的问题吗?
    • 不,排序是O(n log(n)),只是添加元素并重新排序并不总是最好的方法。
    猜你喜欢
    • 2015-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-08-09
    • 1970-01-01
    • 2014-05-02
    • 1970-01-01
    相关资源
    最近更新 更多