我想创建一个hash
,但我只对keys
感兴趣。因此,我希望values
能够拥有最小的内存占用。什么是最适合分配的对象?
nil
?:a
?答案 0 :(得分:5)
您可以使用任何您想要的值,只要您使用相同的值。
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
是直接值(x
,nil
,true
或{{},则值仅保留指向false
的指针或值本身1}})。
在任何一种情况下,使用的内存都是相同的!它将是您平台上指针的大小(即Fixnum
字节)。在C代码中,这对应于0.size
。
小心重用同一个对象(即同一个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
,false
,true
,nil
或Fixnum
,因为符号存储在全球表。 Symbol
在任何地方都是相同的,字符串: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
作为值。
答案 1 :(得分:2)
以下内容适用于官方Ruby实现。其他实现可能在这方面有所不同。
nil
,true
,false
和Fixnum
s在C级别的指针内编码,而所有其他对象将涉及实际指向某处的指针(所以你有指针的空间消耗加上它指向的空间)。所以这些对象是内存占用最小的对象。
其中,nil
在语义上最有意义。