Java - вызов статических методов против ручного встраивания - снижение производительности - PullRequest
12 голосов
/ 11 февраля 2011

Меня интересует, должен ли я вручную вставлять небольшие методы, которые в каком-то чувствительном к производительности алгоритме вызываются 100 000 - 1 миллион раз.JVM придется выяснить, стоит ли включать этот метод (или даже не делать этого).

Однако на днях я заменил этот встроенный вручную код на вызов статических методов и увидел повышение производительности.Как это возможно?Означает ли это, что на самом деле нет никаких накладных расходов и что JVM, встроенная по «своей воле», на самом деле повышает производительность?Или это во многом зависит от платформы / архитектуры?

(В примере, где произошло повышение производительности, была замена подкачки массива (int t = a[i]; a[i] = a[j]; a[j] = t;) статическим вызовом метода swap(int[] a, int i, int j). Другой пример, в котором не былоразница в производительности была, когда я добавил 10-линейный метод, который был вызван 1000000 раз.)

Ответы [ 5 ]

12 голосов
/ 11 февраля 2011

Я видел нечто подобное. «Ручное встраивание» не обязательно быстрее, результирующая программа может быть слишком сложной для анализа оптимизатором.

В вашем примере давайте сделаем некоторые дикие догадки. Когда вы используете метод swap (), JVM может анализировать тело метода и сделать вывод, что, поскольку i и j не меняются, хотя имеется 4 доступа к массиву, требуется только 2 проверки диапазона вместо 4. Также Локальная переменная t не требуется, JVM может использовать 2 регистра для выполнения работы, без использования r / w t в стеке.

Позже тело swap () встраивается в метод вызывающей стороны. Это после предыдущей оптимизации, поэтому сохранения все еще на месте. Возможно даже, что тело метода вызывающей стороны доказало, что i и j всегда находятся в пределах диапазона, поэтому 2 оставшиеся проверки диапазона также отбрасываются.

Теперь в версии, встроенной вручную, оптимизатор должен анализировать всю программу сразу, слишком много переменных и слишком много действий, он может не доказать, что безопасно сохранять проверки диапазона или удалять локальную переменную t. В худшем случае эта версия может потребовать еще 6 обращений к памяти для выполнения подкачки, что является огромным издержками. Даже если читается только 1 дополнительная память, это все равно очень заметно.

Конечно, у нас нет оснований полагать, что всегда лучше выполнять ручное «обрисовывание», то есть извлекать небольшие методы, желая думать, что это поможет оптимизатору.

-

То, что я узнал, это то, что забудь ручную микрооптимизацию. Дело не в том, что мне небезразлично улучшение микропроцессора, я не всегда доверяю оптимизации JVM. Это то, что я понятия не имею, что делать, что приносит больше пользы, чем зла. И я сдался.

9 голосов
/ 11 февраля 2011

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

JVM ищет определенные структуры и имеет некоторые «ручные» оптимизации, когда распознает эти структуры. Используя метод обмена, JVM может распознать структуру и оптимизировать ее по-разному с определенной оптимизацией.

Возможно, вам будет интересно попробовать отладочную версию OpenJDK 7, в которой есть возможность распечатать исходный код, который он генерирует.

2 голосов
/ 13 июня 2012

Извините за поздний ответ, но я только нашел эту тему, и она привлекла мое внимание.

При разработке на Java попробуйте написать «простой и глупый» код. Причины:

  1. оптимизация выполняется во время выполнения (поскольку сама компиляция выполняется во время выполнения). В любом случае компилятор выяснит, какую оптимизацию следует выполнить, поскольку он компилирует не исходный код, который вы пишете, а используемое им внутреннее представление (несколько AST -> код VM -> код VM ... -> преобразования собственного двоичного кода выполняются в время выполнения компилятором JVM и интерпретатором JVM)
  2. При оптимизации компилятор использует некоторые общие шаблоны программирования при принятии решения о том, что оптимизировать; так что помогите ему помочь вам! напишите приватный статический (возможно, также финальный) метод, и он сразу выяснит, что он может:
    • встроенный метод
    • скомпилируйте его в собственный код

Если метод встроен вручную, это всего лишь часть другого метода, который компилятор сначала пытается понять и посмотреть, пора ли преобразовать его в двоичный код или он должен немного подождать, чтобы понять ход программы. Кроме того, в зависимости от того, что делает метод, возможны несколько повторных JIT'ов во время выполнения => JVM создает оптимальный двоичный код только после «разогрева» ... и, возможно, ваша программа завершилась до того, как JVM прогреется (потому что я ожидаем, что в итоге производительность должна быть примерно одинаковой).

Вывод: имеет смысл оптимизировать код на C / C ++ (поскольку перевод в двоичный файл выполняется статически), но те же оптимизации обычно не имеют значения в Java, где компилятор JIT-байтовый код, а не ваш исходный код код. И между прочим, из того, что я видел, javac даже не удосужился оптимизировать:)

1 голос
/ 11 февраля 2011

Однако на днях я заменил этот встроенный вручную код вызовом статических методов и увидел повышение производительности.Как это возможно?

Возможно, профилировщик JVM видит узкое место легче, если он находится в одном месте (статический метод), чем если бы он реализован несколько раз отдельно.

0 голосов
/ 11 февраля 2011

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

Кстати, если его производительность действительно имеет значение, вы можете попробовать это для заменыдва int значения.(Я не говорю, что это будет быстрее, но это может стоить денег.)

a[i] = a[i] ^ a[j];
a[j] = a[i] ^ a[j];
a[i] = a[i] ^ a[j];
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...