我已经实现了一个简单的B-Tree,它将long映射到int。现在,我想使用以下方法估计它的内存使用量(仅适用于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:好的,引入Xmx大大减少了内存使用,但是仍然不清楚为什么我观察到比isLeaf更高的值。(您仍然可以通过对所有构造器使用isLeaf == false来尝试这一点)
Update2:嗯,有些地方很不对劲。当增加每个叶的条目时,人们会假设内存使用量减少(当对两者执行紧凑时),因为较大的数组涉及较少的引用开销(并且btree具有较小的高度)。但是,如果我在每个叶中使用500个条目而不是100个条目,则memoryUsage方法会报告增加的值。
发布于 2013-04-09 18:16:38
哦嘘..。一点新鲜空气解决了这个问题;)
当条目已满时,它将被拆分。在我最初的拆分方法checkSplitEntry
(我想避免浪费内存)中,我犯了一个很大的内存浪费错误:
// left child: just copy pointer and decrease size to index
BTreeEntry newLeftChild = this;
newLeftChild.entrySize = splitIndex;
这里的问题是,旧的子指针仍然是可访问的。因此,在我的memoryUsage方法中,我对一些孩子计数两次(特别是当我没有压缩的时候!)。因此,没有这个技巧,一切都应该很好,我的B-Tree将更有效地内存,因为垃圾收集器可以做它的工作!
https://stackoverflow.com/questions/15897869
复制相似问题