VisualVM java 分析 - 自我执行?
VisualVM java profiling - self time execution?
我有以下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 中,我最终执行了 2 228 212 次方法,其中 (Total Time CPU) :
Self Time 27.9%
Board.play(int, int) 24.6%
MainClass.generateRnadomInt(int) 8.7%
我想知道的是那些 27.9% 的自我执行 (999ms / 2189ms) 是从哪里来的。
我首先认为分配 2 int 可能会减慢该方法的速度,所以我尝试了以下操作:
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 - strange self time
没有。
首先,Visual VM(以及许多其他基于安全点的分析器)inherently misleading. Try using a profiler 不受安全点偏差的影响。例如。 async-profiler 不仅可以显示方法,还可以显示花费最多 CPU 时间的特定 lines/bytecodes。
其次,在您的示例中,playSingleBoard
可能确实需要相对较长的时间。即使没有分析器,我也可以看出这里最昂贵的操作是大量的数组访问。
RAM is the new disk。内存访问不是免费的,尤其是随机访问。特别是当数据集太大无法放入 CPU 缓存时。此外,Java 中的数组访问需要进行边界检查。此外,Java 中没有“真正的”二维数组,它们更像是数组的数组。
这意味着,像 POSSIBLE_PLAYS[subBoard][randomMoveId]
这样的表达式将导致至少 5 次内存读取和 2 次边界检查。并且每次出现 L3 缓存未命中(对于像您的情况这样的大型数组来说很可能),这将导致 ~50 ns latency - 否则时间足以执行一百次算术运算。
我有以下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 中,我最终执行了 2 228 212 次方法,其中 (Total Time CPU) :
Self Time 27.9%
Board.play(int, int) 24.6%
MainClass.generateRnadomInt(int) 8.7%
我想知道的是那些 27.9% 的自我执行 (999ms / 2189ms) 是从哪里来的。 我首先认为分配 2 int 可能会减慢该方法的速度,所以我尝试了以下操作:
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 - strange self time 没有。
首先,Visual VM(以及许多其他基于安全点的分析器)inherently misleading. Try using a profiler 不受安全点偏差的影响。例如。 async-profiler 不仅可以显示方法,还可以显示花费最多 CPU 时间的特定 lines/bytecodes。
其次,在您的示例中,playSingleBoard
可能确实需要相对较长的时间。即使没有分析器,我也可以看出这里最昂贵的操作是大量的数组访问。
RAM is the new disk。内存访问不是免费的,尤其是随机访问。特别是当数据集太大无法放入 CPU 缓存时。此外,Java 中的数组访问需要进行边界检查。此外,Java 中没有“真正的”二维数组,它们更像是数组的数组。
这意味着,像 POSSIBLE_PLAYS[subBoard][randomMoveId]
这样的表达式将导致至少 5 次内存读取和 2 次边界检查。并且每次出现 L3 缓存未命中(对于像您的情况这样的大型数组来说很可能),这将导致 ~50 ns latency - 否则时间足以执行一百次算术运算。