を作成したいのです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のみを保持します。xniltruefalseFixnum
どちらの場合も、使用されるメモリは同じです。プラットフォーム上のポインタのサイズ(つまり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回だけ保存され、コード内のすべてのシンボルで共有されます。truenilFixnumSymbol: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およびFixnums は、C レベルでポインター内にエンコードされますが、他のすべてのオブジェクトには、実際にどこかを指すポインターが含まれます (そのため、ポインターのスペース消費とポインターが指すスペースが加算されます)。したがって、これらのオブジェクトはメモリ フットプリントが最も小さいオブジェクトです。
これらのうち、nil意味的に最も理にかなっています。