Каковы издержки вызова метода в хорошей виртуальной машине Java? - PullRequest
2 голосов
/ 02 декабря 2009

Может кто-нибудь придумать листинг разобранного машинного кода на ассемблере?

Я имею в виду, что по сравнению с обычным вызовом функции в C. должны быть некоторые издержки.

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

Полагаю, где-то есть проверка переполнения стека возврата.

РЕДАКТИРОВАТЬ: я думаю, я должен отметить, что я не программист Java, а писатель компилятора и хочу выяснить, почему Java-приложения настолько медленные, в то время как тесты Java Java Micro сопоставимы с нативным компилированным кодом. Поэтому для меня важно рассмотреть некоторые детали, даже если они занимают всего несколько десятков наносекунд и несколько дополнительных инструкций.

Ответы [ 5 ]

6 голосов
/ 02 декабря 2009

Java не компилируется непосредственно в машинный код, она компилируется в байт-код, который затем либо интерпретируется, либо компилируется в машинный код во время выполнения - я понятия не имею, как получить машинный код во время выполнения, я просто представляю его как эта огромная масса смещающихся, меняющихся байтов, которая в итоге просто выполняет DAMN быстро и надежно.

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

Использование Final может очень помочь, потому что дает подсказки виртуальной машине о том, как можно оптимизировать еще больше.

Поскольку вызов метода на самом деле может быть полностью скомпилирован и в лучшем случае имеет минимальную стоимость - вам действительно не стоит об этом беспокоиться. Просто используйте лучший код и беспокойтесь о проблемах с производительностью, когда у вас есть неверная спецификация производительности (в этот момент точечная оптимизация сделает НАМНОГО лучше, чем попытка исключить вызовы методов в вашем коде, разрушая вашу кодовую базу для всех вовлеченных).

Обратите внимание, что из-за анализа времени выполнения в некоторых очень редких случаях он может быть быстрее, чем аналогичный код на C (компилятор c не будет профилировать во время выполнения и оптимизировать свой код вручную, вам придется сделать все возможное это сам).

3 голосов
/ 02 декабря 2009

В обновленном вопросе ОП написал это:

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

Тогда в комментарии ОП написали:

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

Я думаю, что реальная проблема заключается в том, что ваше мнение о том, что «Java медленная», основано на опыте действительно старой версии Java. JIT JIT-компиляторы значительно улучшились за 9 лет, прошедших с момента выпуска Java 1.3.

Так что, глядя на некоторые детали, важно для меня здесь, даже если они займет всего несколько десятков наносекунд и несколько дополнительных инструкций.

Если вы (по вашему собственному признанию) не программист java, а (не ява, я предполагаю) автор компилятора, почему эти детали важны для вас?

ОБНОВЛЕНИЕ: я нашел эту страницу в Sun Wiki, которая может помочь. Это относится к Java 7, которая доступна только в качестве сборок для разработки, но может быть достаточно подсказок, чтобы помочь вам разобрать JIT-скомпилированный код для текущих выпусков Java.

1 голос
/ 03 декабря 2009

Ну, я никогда не программировал Java с версии 1.3, но я часто использую Eclipse, Netbeans и IntelliJ, и все они такие медленные по сравнению с нативными программами с графическим интерфейсом.

Я не уверен, что у меня есть четкие представления о том, как генерировать статистику для производительности графического интерфейса - измеряете ли вы время, затрачиваемое на выполнение конкретной задачи, используете автоматическое тестирование, или это одна из таких ситуаций? где вы как бы смотрите на это и говорите: «Это медленнее / быстрее, чем программа X». Я не эксперт по родным программам с графическим интерфейсом, но я знаю, что графические интерфейсы в Java часто выглядят медленными не потому, что сама Java обязательно медленная, а потому, что разработчикам графического интерфейса не удалось создать отзывчивый графический интерфейс - ставить долго выполняющиеся задачи на событие Отправка темы, чтобы назвать один пример. В отсутствие хорошо сконструированных сравнительных тестов трудно сказать, в чем вина Java и в чем плохое программирование GUI.

Однако, чтобы ответить на ваш вопрос, Билл К упомянул игру Shootout Computer Programming Shootout в качестве источника многочисленных тестов компиляторов. Еще один интересный источник статистики для платформ Win32 можно найти здесь .

0 голосов
/ 07 декабря 2009

Дело в том, что вы сравниваете яблоки и апельсины. Java компилируется во время выполнения (вы слышали о JIT?), Поэтому он не совсем сопоставим с C, который компилирует в автономном режиме. Большая часть накладных расходов происходит из-за времени, которое вы не учитываете в C (процесс компиляции), а не из "вызова метода", как вы предполагаете

0 голосов
/ 02 декабря 2009

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

Например, JVM может решить встроить ваш метод, и тогда у вас вообще не будет накладных расходов на вызовы. Если метод не встроенный, но все же скомпилирован в собственный код, у вас есть эквивалентные накладные расходы для вызова метода / функции с использованием указателя в C / C ++, плюс требования к компьютеру (например, установка стека, аргументы, эпилог / вводная часть). Это должно составлять примерно до времени выполнения от 10 до 30 собственных инструкций, но это приблизительное значение - вы должны измерить это, если действительно важно.

Цифры должны сильно отличаться, если вы используете JVM только для интерпретации, возможно, с гораздо большими накладными расходами (никогда не проверял это сам, но если бы мне пришлось угадывать, я бы сделал ставку на одну дополнительную величину - около 100 до 300 инструкций).

...