gpt4 book ai didi

java - 为什么分配单个 2D 数组比循环分配多个总大小和形状相同的 1D 数组花费的时间更长?

转载 作者:行者123 更新时间:2023-12-02 07:27:09 26 4
gpt4 key购买 nike

本以为直接创建会更快,但事实上,添加循环只需要一半的时间。到底发生了什么事情速度变慢了?

这是测试代码

@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
public class Test_newArray {
private static int num = 10000;
private static int length = 10;

@Benchmark
public static int[][] newArray() {
return new int[num][length];
}

@Benchmark
public static int[][] newArray2() {
int[][] temps = new int[num][];
for (int i = 0; i < temps.length; i++) {
temps[i] = new int[length];
}
return temps;
}

}

测试结果如下。

Benchmark                Mode  Cnt    Score   Error  Units
Test_newArray.newArray avgt 25 289.254 ± 4.982 us/op
Test_newArray.newArray2 avgt 25 114.364 ± 1.446 us/op

测试环境如下

JMH版本:1.21

虚拟机版本:JDK 1.8.0_212、OpenJDK 64 位服务器虚拟机、25.212-b04

最佳答案

在 Java 中,有一个单独的字节码指令用于分配多维数组 - multianewarray .

  • newArray 基准测试使用 multianewarray 字节码;
  • newArray2 在循环中调用简单的newarray

问题在于 HotSpot JVM 没有用于 multianewarray 字节码的快速路径*。该指令始终在VM运行时执行。因此,分配不会内联在编译的代码中。

第一个基准测试必须付出 Java 和 VM 运行时上下文之间切换的性能损失。此外,VM 运行时中的通用分配代码(用 C++ 编写)并不像 JIT 编译代码中的内联分配那样优化,只是因为它是通用的,即没有针对特定对象类型或对象进行优化对于特定的调用站点,它执行额外的运行时检查等。

以下是使用 async-profiler 分析两个基准的结果。我使用的是 JDK 11.0.4,但对于 JDK 8,图片看起来类似。

newArray

newArray2

第一种情况,99%的时间都花在OptoRuntime::multianewarray2_C里面- VM运行时中的C++代码。

在第二种情况下,图表的大部分是绿色的,这意味着程序主要在 Java 上下文中运行,实际上执行专门针对给定基准优化的 JIT 编译代码。

编辑

* 实际上,HotSpot JVM 可以内联 multianewarray,但前提是分配总数不超过 -XX: MultiArrayExpandLimit 默认为 6。

因此,例如,new int[5][10]将在JIT编译的代码中内联分配,而new int[10][5]的分配code> 将通过 VM 运行时。

关于java - 为什么分配单个 2D 数组比循环分配多个总大小和形状相同的 1D 数组花费的时间更长?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58158445/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com