gpt4 book ai didi

java - 我有一个我不明白的 Java 性能问题

转载 作者:搜寻专家 更新时间:2023-10-30 20:02:37 25 4
gpt4 key购买 nike

我写了一些代码来制作一个多维数组而不是一个数组数组,这样我可以节省一些内存。然后我运行了一些测试,将它的速度与常规 Java 数组数组 (int[][]) 的速度进行比较,因为我不希望我的程序运行得更慢,即使它节省了一些内存。我在计时测试中看到的让我感到困惑。以下是测试运行的典型结果。时间是针对相同的代码位。请注意最后两个比前四个大得多。

time: 58343722 ns
time: 59451156 ns
time: 51374777 ns

time: 61777424 ns
time: 813156695 ns
time: 782140511 ns

现在我首先想到的是垃圾收集器在起作用。我将内存限制提高到 5GB (-Xmx5g),这样垃圾收集器就不会启动。没有改变。我四处移动了一些东西,但模式仍然存在。

那么模式是什么?前三次,这段代码在一个函数中,我调用了它三次。在第二个三次中,代码位在一个函数中重复三次。因此,模式是每当代码位在同一个函数中运行多次时,运行代码位所花费的时间将从第二位代码开始猛增,并在之后保持不变。

我确实找到了一个会产生如下结果的改动:

time: 58729424 ns
time: 59965426 ns
time: 51441618 ns

time: 57359741 ns
time: 65362705 ns
time: 857942387 ns

我所做的是在后三个代码位之间添加一毫秒的延迟。这样做只会加速 block 中的第二个代码位,而任何延迟都不会加速后面的任何代码位。

老实说,我很困惑。我无法解释这种行为。有人可以阐明正在发生的事情吗?

代码如下:

package multidimensionalarraytests;

import java.lang.reflect.Array;
import java.util.logging.Level;
import java.util.logging.Logger;

public class MultidimensionalArrayTests {
static ArrayInt2Dv1 array=new ArrayInt2Dv1(10000,10000);

public static void main(String[] args) {
System.out.println("ignore the warmup");
test();
test();
combined();
combined();

System.out.println("running tests");
test();
test();
test();
System.out.println();
combined();
}

static long test(){
int value=1;
long start,stop,time;

System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
return time;
}

static void combined(){
int value=1;
long start,stop,time;

System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");

//try {Thread.sleep(1);} catch (InterruptedException ex) {}

System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");

//try {Thread.sleep(60000);} catch (InterruptedException ex) {}

System.out.print("time: ");
start=System.nanoTime();
for(int x=0;x<array.length1;x++){
for(int y=0;y<array.length2;y++){
array.set(x, y, value);
value=array.get(x, y);
}
}
stop=System.nanoTime();
time=(stop-start);
System.out.println(time+" ns");
}
}

和:

package multidimensionalarraytests;

public class ArrayInt2Dv1 {
int [] array;

public final int length1;
public final int length2;

public ArrayInt2Dv1(int length1, int length2){
this.length1=length1;
this.length2=length2;
array=new int[length1*length2];
}

public int get(int x,int y){
return array[x*length2+y];
}

public void set(int x,int y,int value){
array[x*length2+y]=value;
}
}

---编辑---

Windows 7 上的输出带有选项 -Xms5g -Xmx5g -XX:+PrintCompilation -verbose:gc -XX:CICompilerCount=1 -Xbatch

time:     299    1    b        multidimensionalarraytests.ArrayInt2Dv1::set (15 bytes)
302 2 b multidimensionalarraytests.ArrayInt2Dv1::get (14 bytes)
303 1 % b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
358 1 % multidimensionalarraytests.MultidimensionalArrayTests::test @ -2 (114 bytes) made not entrant
60671451 ns
359 3 b multidimensionalarraytests.MultidimensionalArrayTests::test (114 bytes)
time: 365 2 % b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
58104484 ns
time: 425 3 % b multidimensionalarraytests.MultidimensionalArrayTests::combined @ 31 (330 bytes)
69008251 ns
time: 806898159 ns
time: 845447596 ns
2146 4 b multidimensionalarraytests.MultidimensionalArrayTests::combined (330 bytes)
time: 52493169 ns
time: 804304528 ns
time: 845500191 ns
running tests
time: 51290771 ns
time: 51922285 ns
time: 51264108 ns

time: 52258679 ns
time: 842229025 ns
time: 871403625 ns

在 Linux 上(同一台机器上的 VirtualBox 上的 Ubuntu)具有相同的选项:

    283   1   b   java.lang.String::hashCode (60 bytes)
285 2 b sun.nio.cs.UTF_8$Encoder::encodeArrayLoop (490 bytes)
287 3 b java.lang.String::charAt (33 bytes)
287 4 b java.lang.String::indexOf (151 bytes)
297 5 b java.io.UnixFileSystem::normalize (75 bytes)
2850 6 b java.lang.String::lastIndexOf (156 bytes)
ignore the warmup
time: 5885 7 b multidimensionalarraytests.ArrayInt2Dv1::set (15 bytes)
5948 8 b multidimensionalarraytests.ArrayInt2Dv1::get (14 bytes)
5949 1% b multidimensionalarraytests.MultidimensionalArrayTests::test @ 31 (114 bytes)
11529998483 ns
17565 9 b multidimensionalarraytests.MultidimensionalArrayTests::test (114 bytes)
time: 1619622928 ns
time: 19718 2% b multidimensionalarraytests.MultidimensionalArrayTests::combined @ 31 (330 bytes)
475786382 ns
time: 288586857 ns
time: 315560700 ns
20789 10 b multidimensionalarraytests.MultidimensionalArrayTests::combined (330 bytes)
time: 460577230 ns
time: 311525066 ns
time: 312343429 ns
running tests
time: 310261854 ns
time: 298826592 ns
time: 304689920 ns

time: 315416579 ns
time: 299473245 ns
time: 290211350 ns

最佳答案

试试 -XX:+PrintCompilation 这应该表明整个方法在第一个循环迭代 10000 次后得到了优化。问题是第二个/第三个循环是在没有统计/计数器信息的情况下优化的。有时这无关紧要,有时后面的循环要慢得多,如果你交换循环的顺序,后面的循环会改进,而第一个循环会变慢。

解决这个问题的简单方法是将每个循环放在它自己的方法中,每个循环都会得到适当的优化。

关于java - 我有一个我不明白的 Java 性能问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8839473/

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