2013-04-09 18 views
5

単純なB-Treeを実装しました。これはlongをintにマップします。今度は、次の方法でメモリ使用量を見積もりました。(32ビットJVMのみに適用):JavaでBツリーのメモリ使用量を計算する

class BTreeEntry { 

    int entrySize; 
    long keys[]; 
    int values[]; 
    BTreeEntry children[]; 
    boolean isLeaf; 
    ... 
    /** @return used bytes */ 
    long capacity() { 
     long cap = keys.length * (8 + 4) + 3 * 12 + 4 + 1; 
     if (!isLeaf) { 
      cap += children.length * 4; 
      for (int i = 0; i < children.length; i++) { 
       if (children[i] != null) 
        cap += children[i].capacity(); 
      } 
     } 
     return cap; 
    } 
} 
/** @return memory usage in MB */ 
public int memoryUsage() { 
    return Math.round(rootEntry.capacity()/(1 << 20)); 
} 

私はそれを試しました。 7mioエントリの場合、memoryUsageメソッドは-Xmxの設定よりもはるかに高い値を報告します!例えば。それは1040(MB)と私は-Xmx300を設定すると言う! JVMは何とかメモリレイアウトを最適化することができますか?空の配列の場合、または私の間違いかもしれませんか?

Update1:​​いいえ、isLeafブール値を導入すると、メモリ使用量が大幅に減少しますが、なぜXmxよりも高い値が観測されたのかはっきりしません。 (これは、すべてのコンストラクタに対してisLeaf == falseを使用して試すことができます)

Update2:うーん、何かが間違っています。リーフあたりのエントリを増やすと、大規模な配列(btreeの高さがより小さい)では参照のオーバーヘッドが少なくなるため、メモリ使用量が減少する(両者をコンパクトにすると)。しかし、memoryUsageメソッドは、リーフあたり100個のエントリを代わりに500個使用すると、値が増えたと報告します。

+0

3 * 12の長年の出所は何ですか? – Erik

+0

longとintのメモリ消費値のソースは? – PeterMmm

+0

@Erik 3 * 12 - > 3つの配列への参照。 – Karussell

答えて

0

おおshの...新鮮な空気は、この問題を解決ビット;)

エントリは、それが分割されますいっぱいです。 (私はメモリの無駄を避けたかった)私のオリジナルの分割方法checkSplitEntryで私は大きなメモリ廃棄物のミスを犯した。

// left child: just copy pointer and decrease size to index 
BTreeEntry newLeftChild = this; 
newLeftChild.entrySize = splitIndex; 

ここでの問題は、古い子供ポインタがまだアクセス可能であること、です。そして、私のmemoryUsageメソッドでは、私はいくつかの子供たちを2回カウントしています(特に私がコンパクトではなかった時)。だから、このトリックがなければ、すべてがうまくいくはずですし、私のBツリーは、ガベージコレクタがその仕事をすることができるので、さらに効率的なメモリになります!

関連する問題