java - Java 6 和 7 之间有什么区别会导致性能问题?

标签 java performance inputstream

我对 Java 7 的一般经验告诉我,它比 Java 6 快。但是,我遇到了足够多的信息,这让我相信并非总是如此。

第一个信息来自发现的 Minecraft Snooper 数据 here .我的目的是查看这些数据以确定用于启动 Minecraft 的不同开关的效果。例如,我想知道使用 -Xmx4096m 是否会对性能产生负面或正面影响。在我到达那里之前,我查看了正在使用的不同版本的 Java。它涵盖了从 1.5 到使用 1.8 的开发人员的所有内容。通常,随着您增加 java 版本,您会看到 fps 性能的提高。在 1.6 的不同版本中,您甚至可以看到这种逐渐上升的趋势。老实说,我没想到会在野外看到这么多不同版本的 java,但我猜人们不会像他们应该的那样运行更新。

在 1.6 的更高版本中,您会获得最高的浏览量。 1.7 的平均速度比 1.6 的更高版本低约 10fps,但仍高于 1.6 的早期版本。在我自己的系统中的样本上,几乎不可能看到差异,但在查看更广泛的样本时,就很清楚了。

为了控制有人可能找到了我控制的 Java 魔术开关的可能性,只查看没有传递任何开关的数据。这样我就可以在开始查看不同的标志之前进行合理的控制。

我忽略了我所看到的大部分内容,因为这可能是一些没有与我分享的 Magic Java 6。

现在我一直在处理另一个项目,该项目需要我在 InputStream 中传递一个数组以由另一个 API 处理。最初我使用 ByteArrayInputStream 因为它可以开箱即用。当我查看它的代码时,我注意到每个函数都是同步的。由于这对这个项目来说是不必要的,所以我重写了一个,去掉了同步。然后我决定我想知道在这种情况下同步的一般成本是多少。

我模拟了一个简单的测试只是为了看看。我使用 System.nanoTime() 对所有内容进行计时,并使用 Java 1.6_20 x86 和 1.7.0-b147 AMD64 和 1.7_15 AMD64 并使用 -server。我预计 AMD64 版本仅基于架构就能胜过任何 java 7 优势。我还查看了第 25、第 50 和第 75 个百分位数(蓝色、红色、绿色)。然而,没有 -server 的 1.6 击败了其他所有配置。 graph

所以我的问题是。 1.6 -server 选项中有什么影响性能,在 1.7 中也默认启用?

我知道 1.7 中的大部分速度增强来自于将 1.6 中一些更激进的性能选项默认为开启,但其中之一是导致性能差异。我只是不知道该看哪些。

public class ByteInputStream extends InputStream {

public static void main(String args[]) throws IOException {
    String song = "This is the song that never ends";
    byte[] data = song.getBytes();
    byte[] read = new byte[data.length];
    ByteArrayInputStream bais = new ByteArrayInputStream(data);
    ByteInputStream bis = new ByteInputStream(data);

    long startTime, endTime;

    for (int i = 0; i < 10; i++) {
        /*code for ByteInputStream*/
        /*
        startTime = System.nanoTime();
        for (int ctr = 0; ctr < 1000; ctr++) {
            bis.mark(0);
            bis.read(read);
            bis.reset();
        }
        endTime = System.nanoTime(); 

        System.out.println(endTime - startTime); 
        */

        /*code for ByteArrayInputStream*/
        startTime = System.nanoTime();
        for (int ctr = 0; ctr < 1000; ctr++) {
            bais.mark(0);
            bais.read(read);
            bais.reset();
        }
        endTime = System.nanoTime();

        System.out.println(endTime - startTime);
    }

}

private final byte[] array;
private int pos;
private int min;
private int max;
private int mark;

public ByteInputStream(byte[] array) {
    this(array, 0, array.length);
}

public ByteInputStream(byte[] array, int offset, int length) {
    min = offset;
    max = offset + length;
    this.array = array;
    pos = offset;
}

@Override
public int available() {
    return max - pos;
}

@Override
public boolean markSupported() {
    return true;
}

@Override
public void mark(int limit) {
    mark = pos;
}

@Override
public void reset() {
    pos = mark;
}

@Override
public long skip(long n) {
    pos += n;
    if (pos > max) {
        pos = max;
    }
    return pos;
}

@Override
public int read() throws IOException {
    if (pos >= max) {
        return -1;
    }
    return array[pos++] & 0xFF;
}

@Override
public int read(byte b[], int off, int len) {
    if (pos >= max) {
        return -1;
    }
    if (pos + len > max) {
        len = max - pos;
    }
    if (len <= 0) {
        return 0;
    }
    System.arraycopy(array, pos, b, off, len);
    pos += len;
    return len;
}

@Override
public void close() throws IOException {
}

}// end class

最佳答案

我认为,正如其他人所说,您的测试太短而无法看到核心问题 - 图表显示的是 nanoTime,这意味着正在测量的核心部分在 0.0001 到 0.0006 秒内完成。

讨论

-server 和 -client 的主要区别在于 -server 期望 JVM 存在很长时间,因此在早期花费精力以获得更好的长期结果。 -client 的目标是快速启动时间和足够好的性能。

特别是热点运行时进行了更多优化,这些优化需要更多 CPU 来执行。换句话说,使用 -server,您可能会看到优化器的成本超过了优化带来的任何 yield 。

Real differences between "java -server" and "java -client"?

另外,您也可能会看到 tiered compilation 的影响。在 Java 7 中,热点并没有那么快启动。只有 1000 次迭代,代码的全面优化要等到以后才能完成,因此 yield 会更少。

如果您使用 -Xprof 选项运行 java,您可能会有所了解,JVM 将转储一些关于在各种方法中花费的时间的数据,包括解释和编译。它应该可以了解编译的内容,以及热点启动之前的 (cpu) 时间比例。

但是,要获得真实情况,您确实需要运行此 更多 时间 - 分钟,而不是毫秒 - 以允许 Java 和操作系统预热。在 main 中循环测试会更好(这样您就有一个包含已检测的主测试循环的循环),这样您就可以忽略预热。

编辑将秒更改为分钟,以确保热点、jvm 和操作系统正确“预热”

关于java - Java 6 和 7 之间有什么区别会导致性能问题?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15145870/

相关文章:

java - Apache Commons CLI DefaultParser NoSuchMethod 错误

javascript - 测试js变量声明速度

performance - 交换两个整数值的最佳方式?

java - 如何读取 BufferedReader 两次或多次?

java - 当InputStream定期接收数据时,它的消息如何永远不会为空?

java - 哪种 equals 方法更优选?

java - 框架上的 Selen 测试

java - android :onClick and View. OnClickListener 之间的关系

java - 无法检索 blob 数据并在 JLabel-mySql 中显示

ios - 在 Grand Central 中跟踪线程的技术?