我不是 JVM 专家,但上次我检查了一个 Java 对象有 8 字节(64 位)的元数据,同样似乎需要 64 位对齐。这在 32 位 Android 设备上可能会有所不同,但根据我的发现,您的 Point 对象需要 16 个字节而不是 6 个字节,如下所示:
public class Point {
// 8 byte metadata
// 6 bytes of data.
short x,y,v;
// 2 bytes of padding for alignment of metadata.
}
... 达到这个效果的东西。因此,这大约是 3 个 16 位 shorts 所需的内存使用量的 2.67 倍。因此,将点的内存减少到一半以下并提高引用局部性的一种解决方案是将所有内容存储在一个或多个巨型 short 数组中,例如:
short xyz[num_points * 3];
这将需要非常、非常、非常接近最佳内存量(只需最轻微的开销,在这种情况下绝对微不足道,用于存储数组的一些元数据,例如其长度)。
也就是说,假设 Point 是 16 字节,这只能解释大约一半的爆炸性内存使用(大约 23 兆字节的点数)。另一个很可能是您的四叉树节点本身。不过,如果使用上述技术,您可以将其从 23 兆字节减少到约 8.6 兆字节。
对于其余的内存使用,我的第一个建议是避免为每个叶节点存储单独的ArrayList。例如,您可以只存储一个索引到一个大数组列表中的第一个点(整个树只有一个),也可以再存储一个整数来存储该叶子中存储的元素数量。这是一个 C-ish 伪代码示例,但您应该能够让您的四叉树节点至少是这样的:
struct QuadTreeNode
{
// Stores AABB.
float x1, x2, y1, y2;
// Stores first child or -1 if empty.
int first_child;
// Stores first element or -1 if this is not a leaf.
int first_element;
};
struct QuadTree
{
// Stores all the nodes in the quad tree. The 4
// children of a node are stored contiguously.
QuadTreeNode nodes[];
// Stores all the elements in the quad tree. The
// elements at the leaves are stored contiguously.
Element elements[];
};
这甚至不是很紧凑,但相当紧凑。