Подтвердить что ты не робот

В чем разница между Java 6 и 7, которая может вызвать проблемы с производительностью?

Мой общий опыт работы с Java 7 говорит мне, что он быстрее, чем Java 6. Однако я столкнулся с достаточной информацией, которая заставляет меня поверить, что это не всегда так.

Первый бит информации поступает из данных Minecraft Snooper, найденных здесь. Мое намерение состояло в том, чтобы посмотреть на эти данные, чтобы определить влияние различных переключателей, используемых для запуска Minecraft. Например, я хотел знать, имел ли использование -Xmx4096m отрицательный или положительный эффект на производительность. Прежде чем я смог добраться туда, я посмотрел на другую используемую версию Java. Он охватывает все от 1,5 до разработчика с использованием 1,8. В общем, при увеличении версии Java вы видите увеличение производительности fps. В разных версиях 1.6 вы даже видите эту постепенную тенденцию. Я, честно говоря, не ожидал увидеть столько разных версий Java, которые все еще находятся в дикой природе, но я думаю, что люди не запускают обновления, как должны.

Некоторое время в более поздних версиях 1.6 вы получаете самые высокие зазоры. 1.7 выполняет около 10 кадров в секунду ниже более поздних версий 1.6, но все же выше, чем ранние версии 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 без "-сервера" избили штаны любой другой конфигурации. 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
4b9b3361

Ответ 1

Я думаю, что, как говорят другие, ваши тесты слишком коротки, чтобы увидеть основные проблемы - на графике отображается nanoTime, и это означает, что измеряемая часть ядра завершается в 0,0001-0,0006s.

Обсуждение

Ключевое различие в -server и -client заключается в том, что -сервер ожидает, что JVM будет находиться в течение длительного времени и, следовательно, затратит усилия на ранних этапах для достижения более долгосрочных результатов. -клиент нацелен на быстрое время запуска и хорошую производительность.

В частности, hotspot работает с большим количеством оптимизаций, и для этого требуется больше CPU. Другими словами, с -server вы можете видеть, что стоимость оптимизатора перевешивает любые выгоды от оптимизации.

См. Реальные различия между "java -сервером" и "java -client" ,

В качестве альтернативы вы также можете увидеть эффекты многоуровневую компиляцию, где в Java 7 точка доступа не запускается так быстро. Всего лишь 1000 итераций, полная оптимизация вашего кода не будет выполняться дольше, и поэтому преимущества будут меньше.

Вы можете получить представление о том, что если вы запускаете java с опцией -Xprof, JVM сбрасывает некоторые данные о времени, потраченном различными способами, как интерпретируемыми, так и скомпилированными. Он должен дать представление о том, что было скомпилировано, и о соотношении (cpu) времени до того, как горячая точка зашла.

Однако, чтобы получить истинное изображение, вам действительно нужно запустить это намного дольше - seconds минут, а не миллисекунд - чтобы позволить Java и ОС прогреваться. Было бы даже лучше провести цикл в main (так что у вас есть цикл, содержащий ваш основной тестовый цикл), чтобы вы могли игнорировать разминку.

EDIT Изменены секунды до минут, чтобы убедиться, что точка доступа, jvm и ОС должным образом разогреты