Ruby 可以分配给变量的内存占用率最低的对象是什么?
我想创建一个Ruby 可以分配给变量的内存占用率最低的对象是什么?,ruby,Ruby,我想创建一个散列,但我只对键感兴趣。因此,我希望值具有尽可能小的内存占用。最适合指定的对象是什么 nil 非常短的符号,如:a 更小的 以下内容适用于官方Ruby实现。在这方面,其他实现可能有所不同 nil、true、false和Fixnums在C级的指针内部进行编码,而所有其他对象都会涉及一个实际指向某处的指针(因此指针的空间消耗量加上它指向的空间)。因此,这些对象的内存占用最小 其中,nil在语义上最有意义。您可以使用任何想要的值,只要使用相同的值 x = "A string value"
散列
,但我只对键
感兴趣。因此,我希望值
具有尽可能小的内存占用。最适合指定的对象是什么
nil
- 非常短的符号,如
:a
- 更小的
- 以下内容适用于官方Ruby实现。在这方面,其他实现可能有所不同
nil
、true
、false
和Fixnum
s在C级的指针内部进行编码,而所有其他对象都会涉及一个实际指向某处的指针(因此指针的空间消耗量加上它指向的空间)。因此,这些对象的内存占用最小
其中,
nil
在语义上最有意义。您可以使用任何想要的值,只要使用相同的值
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
或Fixnum
)的值本身
无论哪种情况,使用的内存都是相同的它将是平台上指针的大小(即0.size
bytes)。在C代码中,这对应于一个值
只需小心重用相同的对象(即相同的对象\u 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
或一个符号,因为符号存储在全局表中<代码>: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
作为值。您正在尝试模拟一个集合吗?你知道,stdlib有一套。是的,我知道。我试图模拟一个集合
,但我需要它是一个散列
。我能问一下为什么会有这样奇怪的要求吗?当然。请看@DigitalRoss的回复:我认为你的回答有误导性。这也是一个很好的解释,谢谢。但根据@sepp2k的说法,存储指向x
的指针的占用空间比存储nil
或true
的占用空间要大一些,这意味着h2>h对吗?@sepp2k的回答具有误导性。指针占用的内存与nil
或true
相同,至少在MRI中是这样。我本想将此作为正确答案,但问题是分配给变量的最小内存占用是多少。实际上,如果您使用与nil
、true
或false
不同的内容,您仍然需要将指针值或变量值存储在某个位置。不过差别很小。@joscas:除非这个对象已经存在,比如类,一些常量(比如Float::INFINITY
),等等。。。理解才是最重要的。在任何情况下,都没有理由担心:某些符号所占用的两个字节!