Java 中内存方面的数组与矩阵

Array vs Matrix in terms of memory in Java

我正在做一个涉及启发式的项目,我用 Java 构建了它(应该用 C 语言构建)。 我 运行 遇到了记忆问题。

我的树是用对象节点构建的,每个对象包含一个数组、一个矩阵和三个整数。 我已经削减了许多其他值,以尝试节省更多内存space,但是,这仍然不够。

所以,我在想我也可以将矩阵进行切割,并将其转换为数组。 但是,我的整个项目都是建立在坐标上的,以达到矩阵中的某个点。 因此,在我进行任何更改之前,我想知道这会对内存使用产生多大(或不太大)的影响。

编辑:数组和矩阵均由 int 基元组成。

数组为array[25],矩阵为matrix[5][5].

矩阵表示游戏的棋盘,包含该字段是否为空或是否有某种类型的棋子(均为 int)的信息。

我说的是 16GB 的 RAM 使用量和 2500 万个节点。

我做了这个方法,克隆数组:

public int[] cloneArray(int[] array){
    int i = 0;
    int[] clone = new int[array.length];
    while (i < array.length){
        clone[i] = array[i];
        i++;
    }
    return clone;
}

采用了类似的方法来克隆矩阵和对象本身。

编辑: 在发现分析器的存在后,我进行了检查。 这是结果的屏幕截图:

我认为这些数字是有道理的,因为在控制台中,您可以看到与在分析器中看到的几乎一样多的节点数,状态(在控制台中,"estados" 是当前正在展开的状态指针)。

因此,在分析器中,我们可以看到将近 20m 个状态,它们是生成的节点。 每个状态包含 1 个数组和 1 个矩阵。

我们可以看到138m的数组,除以6等于23m。 又因为一个矩阵是5x5,那么矩阵中包含了5x23m的数组,另外23m是数组

我说得有道理吗?这个解读准确吗?

这是一个保管箱 link,因此您可以查看全分辨率图像: https://www.dropbox.com/s/7wxz8vch1wnrsyr/Untitled.png?dl=0

您的问题可能暗示您的代码中存在隐藏问题,而不是 "out of memory problem"。堆内存并没有那么快完成,你需要你的代码非常重才能到达那里。

不过,我敢说将二维矩阵更改为数组不会对内存使用量产生太大影响。 关于哪个 - 实现高维数组(2 及以上)的 2 种最常见方法是 1) 将其切片为一维数组,然后使用公式:

arr[a][b].. = arr[a+b+..]

2) 使用指向指针的指针,然后你得到一个指针数组,它指向另一个指针数组,依此类推,直到最后一层是真实的对象

这就是说,(再次,敢于),Java 可能已经在幕后将矩阵切成一维数组。

无论如何,我高度怀疑您的代码中有内存泄漏,或者没有结束递归,或者以上的组合。在尝试实施您的建议之前,请先看看您不在那里。

这里有几个例子:

int[] array = new int[25];

int[][] matrix = new int[5][5];

数组占用的space为:

  • 25 x 4 字节整数(数组内容)
  • 12 字节的数组对象头
  • 共112字节

Java中的一个二维int矩阵实际上是一个数组的数组,所以矩阵所占的space为

  • (5 x 4 字节整数 + 12 字节数组头)x 5.
  • 5 x 4 字节引用 + 12 字节数组头
  • 共192字节

(以上假定 32 位 JVM 和 典型 数组头大小。这些是特定于平台的假设,但对于任何 JVM 平台,您应该能够将它们与特异性。对于自 Java 6 以来的 Oracle HotSpot / OpenJDK JVM,源代码可供任何人查看。)

当然请注意,随着数组/矩阵变大,int[N^2] 相对于 int[N][N] 的相对节省会变小。