【问题标题】:What is the lowest memory occupancy object that can be assigned to a variable?可以分配给变量的最低内存占用对象是多少?
【发布时间】:2013-02-06 18:19:13
【问题描述】:

我想创建一个hash,但我只对keys 感兴趣。因此,我希望values 拥有尽可能最小的内存占用。最适合分配的对象是什么?

  • nil?
  • 一个很短的符号,比如:a ?
  • 更小的东西?

【问题讨论】:

  • 你想模仿一个集合吗?你知道,stdlib 中有一个集合。
  • 是的,我知道。我正在尝试模拟Set,但我需要它是Hash
  • 我能问一下为什么会有这么奇怪的要求吗?
  • 当然。查看@DigitalRoss 的回复:stackoverflow.com/questions/14731230/…

标签: ruby


【解决方案1】:

你可以使用任何你想要的值,只要你使用相同的值。

x = "A string value"
h =  Hash[ 10000.times.map{|i| [i, x]} ]
h2 = Hash[ 10000.times.map{|i| [i, nil]} ]
# h takes the same memory as h2

在上面的例子中,x 可以是你喜欢的任何东西。如果x 是立即值(niltruefalseFixnum),这些值将只保存指向x 的指针或值本身。

在任何一种情况下,使用的内存都是相同的!它将是您平台上指针的大小(即0.size 字节)。在 C 代码中,这对应于 VALUE

请注意重复使用相同的对象(即相同的object_id),而不是每次都创建新对象。例如:

h3 =  Hash[ 10000.times.map{|i| [i, "A string value"]} ]
# => h3 will take a lot more space!
h.values.map(&:object_id).uniq.size  # => 1
h3.values.map(&:object_id).uniq.size # => 10000

简而言之,一个可靠的方法是使用falsetruenilFixnumSymbol,因为符号存储在全局表中。 :hello.object_id 在任何地方都是相同的,字符串 'hello' 只存储一次,并为代码中的所有 :hello 符号共享。

h4 =  Hash[ 10000.times.map{|i| [i, :some_symbol]} ]
# => h4 will only take as much space as h and h2
h4.values.map(&:object_id).uniq.size # => 1

仅供参考,内置库 Set 具有相同的要求,即它仅将 Hash 用于键。为简单起见,它使用true 作为值。

【讨论】:

  • +1 这也是一个很好的解释,谢谢。但根据@sepp2k,存储指向x 的指针比存储niltrue 更大,这意味着h2 > h 对吗?
  • @sepp2k 的回答具有误导性。至少在 MRI 中,指针占用与 niltrue 相同的内存。
  • 我想将其分配为正确答案,但问题是分配给变量的最小占用空间是多少。实际上,如果您使用不同于niltruefalse 的东西,您仍然必须将指针值或变量值存储在某处。不过差别很小。
  • @joscas:除非那个对象已经存在,比如一个类,一些常量(比如Float::INFINITY)等等......理解才是最重要的。无论如何,没有理由担心:some_symbol 占用的几个字节!
【解决方案2】:

以下内容适用于官方的 Ruby 实现。其他实现可能在这方面有所不同。

niltruefalseFixnums 在 C 级别的指针内编码,而所有其他对象将涉及一个实际指向某处的指针(所以你会有空间消耗指针加上它指向的空间)。所以这些对象是内存占用最小的对象。

其中,nil 在语义上最有意义。

【讨论】:

  • 我认为您的回答具有误导性。见我的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-05-14
  • 1970-01-01
  • 2014-03-02
  • 2020-03-12
  • 2011-09-26
  • 2011-02-20
  • 1970-01-01
相关资源
最近更新 更多