Производительность Java: почему вызов метода может быть быстрее, чем прямые вычисления в случае условной индексации и индексации массива? - PullRequest
2 голосов
/ 09 октября 2011

У меня есть следующий метод в приложении Java:

public void setPixel(int x, int y, int rgb) {
    if (isValidPixel(x, y)) {
        bitmap[indexOf(x, y)] = rgb;            
    }
}

Когда я ставлю прямые вычисления вместо вызовов методов, например:

public void setPixel(int x, int y, int rgb) {
    if (x < width && y < height) {
        bitmap[y * width + x] = rgb;            
    }
}

код выполняется на 4-5 миллисекунд дольше, чем первый. Так почему?

Ответы [ 3 ]

2 голосов
/ 09 октября 2011

Если ваши числа верны и воспроизводимы, наиболее вероятным ответом является то, что JIT-компилятору удается компилировать метод, но он отказывается от встроенного оператора. Вы можете отключить JIT-компилятор , чтобы доказать теорию.

1 голос
/ 09 октября 2011

Это почти наверняка тот случай, когда ваши методы оптимизируются ранее, чтобы первый случай выглядел быстрее.

Я предлагаю вам выполнить оба теста в течение как минимум 2-10 секунд в обоих заказах (попробуйте сначала один,а потом второй) прежде чем пытаться сделать какие-либо выводы.

Я бы ожидал, что первый случай встроит свои методы и сделает его точно таким же, как и второй.

0 голосов
/ 16 ноября 2012

В сообщениях leonm это, вероятно, проблема JIT-компилятора.

JIT-компилятор работает с вашим скомпилированным Java-кодом (байт-кодом), а когда часто вызывается некоторая часть кода, он преобразуется в двоичный (машинный) код, который даже быстрее интерпретируемого байт-кода.

Байт-код, который выбирается для преобразования в двоичный код, может определяться несколькими правилами.Некоторые из правил заключаются в том, что ваш код находится в отдельных очень коротких методах и код внутри циклов.

Проблема этой проблемы в том, что короткие методы обычно имеют право переводить намного раньше, чем встроенный код в какой-то более крупный фрагмент кода или метода,Особенно если петли нет или вызывается редко.

Не забывайте, что если вы дублируете один и тот же встроенный код в нескольких местах, он JIT-компилируется отдельно, а сокращенный общий метод переводится преимущественно.

Если вы отключите JIT-компилятор, тогда виртуальная машина javaСкомпилируйте все ваше приложение в двоичный код на этапе запуска, и тогда не должно иметь значения, вызываете ли вы некоторые функциональные возможности с помощью метода или как прямой встроенный код.

Если вы хотите проверить производительность даже с включенным JIT-компилятором, вам следует выполнить теплыйфаза перед тестированием.Эта разминка указывает компилятору JIT, что некоторый фрагмент кода вызывается часто, и компилятор переводит его в двоичный код на заднем плане.

Код прогрева может выглядеть так:

public void testSetPixel() {
  // warm up
  for (int i=0; i < 1000; i++) {
    setPixel(i, i, 10);
  }
  // your regular testing code with testing setPixel(int, int, int) method
  ...
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...