在Java中计算B树的内存使用情况

时间:2013-04-09 09:10:48

标签: java memory-management jvm b-tree

我已经实现了一个简单的B-Tree,它将longs映射到整数。现在我想使用以下方法估计它的内存使用量(仅适用于32位JVM):

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方法会报告增加的值。

1 个答案:

答案 0 :(得分:0)

哦......有点新鲜空气解决了这个问题;)

当条目已满时,它将被分割。在我原来的拆分方法checkSplitEntry中(我想避免浪费内存)我犯了很大的内存浪费错误:

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

这里的问题是,仍然可以访问旧的儿童指针。所以,在我的memoryUsage方法中,我计算了一些孩子两次(特别是当我没有压缩时!)。因此,如果没有这个技巧,一切都应该没问题,而且我的B-Tree将更加节省内存,因为垃圾收集器可以完成它的工作!