【问题标题】:Does Ruby recalculate array size every time when you call `array.size`?每次调用 `array.size` 时,Ruby 都会重新计算数组大小吗?
【发布时间】:2020-06-09 15:58:45
【问题描述】:

有人可以提供一些证据,Ruby 是否每次调用 array.sizearray.lengtharray.count 时都会重新计算数组大小?

提前致谢。

更新

为了让事情更清楚,recalculate 我的意思是,当我们每次调用array.size 时,Ruby 是否需要一次又一次地遍历整个数组来计算其元素的数量。

【问题讨论】:

  • 不,Ruby 会跟踪数组大小。调用 array.size 几乎没有开销。
  • @Stefan,这是有趣且有用的信息。哈希、集合、范围、字符串呢?那么从数组派生的枚举器呢,比如[1,2,3].each
  • Marian13,您的问题有些模棱两可,因为不清楚您所说的“重新计算”是什么意思。有人可能会争辩说,每当调用方法或检索变量的值时,都会发生“计算”。我将您的问题解释为一个实际问题,例如,询问n = arr1.size; arr2.select { |x| x < n } 是否比arr2.select { |x| x < arr1.size }明显更有效,这是我对自己的疑惑。用@Stefan 的话来说,也许你在问“Ruby 是否会跟踪数组大小”?
  • @Cary Swoveland,您正确地解释了我的问题。 “Ruby 是否跟踪数组大小?”正是我想知道的。我会更新我的问题以使事情更清楚。
  • 我查过一次。您可以通过基准测试 size 来轻松验证 10 元素和 1000 万元素数组 - 应该没有任何区别(但不要测量数组创建时间)

标签: arrays ruby


【解决方案1】:

务实地说,Array#length 在 Ruby 中是动态的

您的问题无法真正得到规范的回答,因为数组的查找和存储实现通常是特定于平台和虚拟机的。然而,实际上,从 Ruby 解释器的角度来看,答案是 yes,因为每次调用都会向 Array 对象发送一个 消息,要求它返回其当前长度。

某些语言将数组的当前长度存储为数组本身的一个元素。也存在其他方法。在 Ruby 2.7.1 中:

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

C 实现似乎在调用时检索存储的数组长度,但如果您想了解 VM 的所有细节,则必须深入挖掘源代码优化这个(或不优化)。

【讨论】:

  • github.com/ruby/ruby/blob/master/include/ruby/internal/core/… 的实现似乎通过查询存储长度以恒定时间运行。
  • 事实上RARRAY 似乎将长度存储在C Struct 中,而RARRAY_LEN(ary) 所做的只是获取该值(RARRAY(s)->len
  • 核心类对性能至关重要。虽然这没有记录在案,但看到没有优化这些的 Ruby 实现,我会感到非常惊讶。
猜你喜欢
  • 2016-08-29
  • 2022-07-27
  • 2016-07-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-09
  • 2015-12-24
相关资源
最近更新 更多