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

med*_*380 25 java performance inputstream

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

第一部分信息来自此处的 Minecraft Snooper数据.我的目的是查看这些数据,以确定用于发射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百分位数(蓝色,红色,绿色).然而1.6没有服务器击败了其他任何配置的裤子. 图形

所以我的问题是.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
Run Code Online (Sandbox Code Playgroud)

And*_*ock 5

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

讨论

-server和-client的关键区别在于-server期望JVM长时间存在,因此需要尽早花费精力来获得更好的长期结果.-client旨在实现快速启动时间和良好的性能.

特别是热点运行具有更多优化,并且这些需要更多的CPU来执行.换句话说,使用-server,您可能会看到优化器的成本超过优化的任何收益.

看看"java -server"和"java -client"之间的真正区别?

或者,您可能也会看到分层编译的效果,在Java 7中,热点不会如此快速地发挥作用.只需1000次迭代,您的代码的完全优化将在以后完成,因此效益会更低.

如果您使用-XprofJVM将转储有关在各种方法(解释和编译)中花费的时间的一些选项来运行java,您可能会深入了解.它应该对编译的内容和热点启动前的(cpu)时间比例有所了解.

然而,为了获得真实的图像,你真的需要运行这么长时间 - 分钟,而不是毫秒 - 以允许Java和操作系统预热.将测试循环到更好main(所以你有一个包含你的仪器化主测试循环的循环),这样你就可以忽略预热.

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