を作成したいのですhash
が、 にしか興味がありませんkeys
。結果として、可能な限り最小のメモリ フットプリントvalues
を持つようにしたいと考えています。割り当てるのに最も適したオブジェクトは何ですか?
nil
?:a
?のような非常に短い記号- もっと小さいもの?
を作成したいのですhash
が、 にしか興味がありませんkeys
。結果として、可能な限り最小のメモリ フットプリントvalues
を持つようにしたいと考えています。割り当てるのに最も適したオブジェクトは何ですか?
nil
?:a
?のような非常に短い記号同じ値を使用する限り、任意の値を使用できます。
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
バイト)になります。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
つまり、シンボルはグローバルテーブルに格納されるためfalse
、確実な方法は、、、、、またはを使用することです。はどこでも同じであり、文字列は1回だけ保存され、コード内のすべてのシンボルで共有されます。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
、キーにのみ使用します。true
簡単にするために、値として使用します。
以下は、公式の Ruby 実装に適用されます。他の実装では、この点が異なる場合があります。
nil
、true
、false
およびFixnum
s は、C レベルでポインター内にエンコードされますが、他のすべてのオブジェクトには、実際にどこかを指すポインターが含まれます (そのため、ポインターのスペース消費とポインターが指すスペースが加算されます)。したがって、これらのオブジェクトはメモリ フットプリントが最も小さいオブジェクトです。
これらのうち、nil
意味的に最も理にかなっています。