VisualVM java评测-自时间执行



我有以下Java方法:

static Board board;
static int[][] POSSIBLE_PLAYS; // [262143][0 - 81]
public static void playSingleBoard() {
int subBoard = board.subBoards[board.boardIndex];
int randomMoveId = generateRandomInt(POSSIBLE_PLAYS[subBoard].length);
board.play(board.boardIndex, POSSIBLE_PLAYS[subBoard][randomMoveId]);
}

访问的数组在运行时不会更改。该方法总是由同一个线程调用。board.boardIndex可能从0变为8,总共有9个子板。

在VisualVM中,我最终得到了执行2228212次的方法,其中(Total Time CPU(:

Self Time 27.9%
Board.play(int, int) 24.6%
MainClass.generateRnadomInt(int) 8.7%

我想知道的是,那些27.9%的自我执行(999ms/2189ms(来自哪里。我最初认为分配2int可能会减慢该方法的速度,所以我尝试了以下方法:

public static void playSingleBoard() {
board.play(
board.boardIndex,
POSSIBLE_PLAYS[board.subBoards[board.boardIndex]]
[generateRandomInt(POSSIBLE_PLAYS[board.subBoards[board.boardIndex]].length)]
);
}

但最终得到了类似的结果,我不知道这个自执行时间是什么……是GC时间吗?内存访问?

我已经尝试过这里提到的JVM选项=>VisualVM-奇怪的自我时间和没有。

首先,Visual VM(以及许多其他基于安全点的评测器(本质上具有误导性。尝试使用一个不受安全点偏见影响的探查器。例如,异步探查器不仅可以显示方法,还可以显示花费最多CPU时间的特定行/字节码。

其次,在您的示例中,playSingleBoard可能确实需要相对较长的时间。即使没有探查器,我也可以看出这里最昂贵的操作是大量的数组访问。

RAM是新的磁盘。内存访问不是免费的,尤其是随机访问。尤其是当数据集太大而无法放入CPU缓存时。此外,Java中的数组访问需要进行边界检查。此外,不存在";真";二维数组在Java中,它们相当于数组的数组
这意味着,像POSSIBLE_PLAYS[subBoard][randomMoveId]这样的表达式将导致至少5次内存读取和2次边界检查。每次出现三级缓存未命中(可能是像您的情况下这样的大型阵列(,都会导致约50 ns的延迟,否则这段时间足以执行一百次算术运算。

最新更新