arrays - 为什么不保留空数组和哈希值?

标签 arrays ruby optimization language-lawyer

最近我发现 Ruby 没有优化 []{} 以驻留在指向一个公共(public)共享对象。演示:

irb(main):001:0> [].object_id
=> 70284401361960
irb(main):002:0> [].object_id
=> 70284392762340 # different
irb(main):003:0> [].object_id
=> 70284124310100 # different

irb(main):005:0> {}.object_id
=> 70284392857480
irb(main):006:0> {}.object_id
=> 70284392870480 # different
irb(main):007:0> {}.object_id
=> 70284392904360 # different

我知道空散列和数组文字通常用于初始化将立即发生变异的值。但即使您改用 [].freeze.object_id{}.freeze.object_id 也会发生这种情况。

String 对比,当环境变量 RUBYOPT 设置为 --enable-frozen-string-literal 时:

irb(main):001:0> ""
=> 70284400947400
irb(main):002:0> ""
=> 70284400947400 # same
irb(main):003:0> ""
=> 70284400947400 # same

即使您不启用卡住字符串文字,如果您改为调用 "".freeze.object_id,您每次都会获得相同的对象 ID,尽管我怀疑初始 "" 文字仍然分配了一个中间字符串对象,正在调用 freeze

在对性能敏感的代码库中(好吧,作为对性能敏感的你可以允许自己在仍然使用 MRI 的同时大声笑)我已经看到了这个解决方法,它使用以下共享常量而不是 []{} 对于散列或数组不需要可变的情况:

module LessAllocations
  EMPTY_HASH = {}.freeze
  EMPTY_ARRAY = [].freeze

  # String literals are already frozen, use '' instead
  # EMPTY_STRING = ''
end

所以我的问题是:

  1. 这是错失的优化机会吗?

    似乎可以将窥孔优化写入实习生卡住的空哈希或数组文字。需要成为语言语义的一部分,即是否存在任何可观察到的差异(显然除了 object_id 的行为之外)?

  2. 空哈希和数组文字是否由标记指针表示?它们甚至会导致任何分配发生吗?

最佳答案

Is this a missed optimization opportunity?

要回答这个问题,必须对现实世界的内存使用情况进行调查,但我认为这不太可能。你可以做个小实验...

class Array
  EMPTY_ARRAY = [].freeze
  
  def freeze
    empty? ? EMPTY_ARRAY : super
  end
end

空对象非常小。与您的程序使用内存的其他所有内容相比,它们使用大量内存是一种边缘情况。

I understand that often empty hashes and array literals are used to initialize values that will be immediately mutated.

因此,向空哈希和数组添加写时复制可能会降低速度。

But this happens even if you do [].freeze.object_id or {}.freeze.object_id instead.

卡住它们意味着您提前知道它们将保持空状态,这种情况极为罕见。有这么多已知的空哈希和数组成为性能问题是一种边缘情况。不断的解决方法似乎很好。

关于arrays - 为什么不保留空数组和哈希值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66393640/

相关文章:

regex - 如何优化 grep 正则表达式以匹配 URL

mongodb - 如果不存在,如何在所有文档中插入字段

java - Java中每次出现一个字母就分割一个数组,形成一个更长的数组

c - 替换c字符串中的最后一个单词

python - 在 NumPy 中转置存储在一维数组中的矩阵的最快方法?

css - 使用 materialize rails 4.2 时无法添加 collection_select

ruby-on-rails - 将 ActiveRecord 查询作为变量返回,而不是散列?

c++ - 如何使用自定义 STL vector 类避免智能指针 delete[] 异常?

数组的 Ruby 散列输出 {}

mysql - 为什么 MySQL 不使用我的索引?优化mysql select查询