2013-04-09 80 views
5

我已經實現了一個簡單的B-Tree它將多個長整數映射爲整數。現在,我想用下面的方法來估算它的內存使用情況(適用於32bit的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的高度較小)。但是,如果我使用500個而不是每個葉片100個條目,memoryUsage方法會報告增加的值。

+0

3 * 12長容量的起源是什麼? – Erik 2013-04-09 09:43:45

+0

Long和int的內存消耗值的來源是什麼? – PeterMmm 2013-04-09 09:53:44

+0

@Erik 3 * 12 - >引用3個數組。 – Karussell 2013-04-09 10:12:21

回答

0

喔SH ...有點新鮮空氣解決這個問題;)

當條目已滿,將被分裂。在我原來的拆分方法checkSplitEntry(這裏我想避免浪費內存),我犯了一個很大的浪費內存錯誤:

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

是這裏的問題,舊的孩子指針仍然可以訪問。所以,在我的memoryUsage方法中,我計數了兩次孩子(尤其是當我沒有壓縮!)。所以,如果沒有這個技巧,一切都會好起來的,我的B-Tree將會更加高效,因爲垃圾收集器可以完成它的工作!