Почему Java быстрее при использовании JIT по сравнению с компиляцией в машинный код?

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

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

48
задан Adam Goode 9 December 2009 в 18:50
поделиться

8 ответов

Настоящий убийца для любого компилятора AOT:

Class.forName(...)

Это означает, что вы не можете написать компилятор AOT который охватывает ВСЕ Java-программы, поскольку информация о характеристиках программы доступна только во время выполнения. Однако вы можете сделать это на подмножестве Java, что, как я считаю, делает gcj.

Другой типичный пример - это способность JIT встраивать методы, такие как getX (), непосредственно в вызывающие методы, если обнаруживается, что это безопасно, и если нужно, отменив его, даже если программист явно не помог, сообщив, что метод является окончательным. JIT может видеть, что в запущенной программе данный метод не переопределяется и поэтому в этом случае может рассматриваться как окончательный. Это может быть другим в следующем вызове.

23
ответ дан 7 November 2019 в 12:08
поделиться

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

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

37
ответ дан 7 November 2019 в 12:08
поделиться

Способность Java встраиваться через границы виртуальных методов и выполнять эффективную диспетчеризацию интерфейсов требует анализа времени выполнения перед компиляцией - другими словами, для этого требуется JIT. Поскольку все методы виртуальные, а интерфейсы используются «повсюду», это имеет большое значение.

6
ответ дан 7 November 2019 в 12:08
поделиться

Теоретически JIT-компилятор имеет преимущество перед AOT , если он имеет доступно достаточно времени и вычислительных ресурсов . Например, если у вас есть корпоративное приложение, работающее днями и месяцами на многопроцессорном сервере с большим количеством ОЗУ, JIT-компилятор может создать лучший код, чем любой компилятор AOT.

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

нет шансов против АОТ.

Однако все вышесказанное было только теорией. На практике, Создание такого продвинутого JIT-компилятора намного сложнее, чем достойного AOT-компилятора. Как насчет некоторых практических доказательств ?

6
ответ дан 7 November 2019 в 12:08
поделиться

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

11
ответ дан 7 November 2019 в 12:08
поделиться

JIT-компилятор Java также ленив и адаптивен.

Ленивый

Из-за своей лени он компилирует методы только тогда, когда добирается до них, вместо компиляции всей программы (очень полезно, если вы этого не сделаете) t использовать часть программы). Загрузка классов на самом деле помогает ускорить JIT, позволяя игнорировать классы, с которыми он еще не сталкивался.

Адаптивный

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

23
ответ дан 7 November 2019 в 12:08
поделиться

JIT могут идентифицировать и устранять некоторые условия, которые могут быть известны только во время выполнения. Ярким примером является устранение виртуальных вызовов, используемых современными виртуальными машинами - например, когда JVM находит инструкцию invokevirtual или invokeinterface , если был загружен только один класс, переопределяющий вызываемый метод, Виртуальная машина действительно может сделать этот виртуальный вызов статическим и, таким образом, встроить его. С другой стороны, для программы на C указатель на функцию всегда является указателем на функцию, и ее вызов не может быть встроен (во всяком случае, в общем случае).

Вот ситуация, когда JVM может встроить виртуальный вызов:

interface I { 
    I INSTANCE = Boolean.getBoolean("someCondition")? new A() : new B();
    void doIt(); 
}
class A implements I { 
    void doIt(){ ... } 
}
class B implements I { 
    void doIt(){ ... } 
}
// later...
I.INSTANCE.doIt();

Предполагая, что мы не будем создавать экземпляры A или B где-либо еще и что someCondition имеет значение true , JVM знает, что вызов doIt () всегда означает A.doIt , и поэтому может избежать поиска в таблице методов, а затем встроить вызов. Подобная конструкция в среде без JITted не может быть встраиваемой.

6
ответ дан 7 November 2019 в 12:08
поделиться

Я думаю, что тот факт, что официальный компилятор Java является JIT-компилятором, является значительной частью этого. Сколько времени было потрачено на оптимизацию JVM по сравнению с компилятором машинного кода для Java?

2
ответ дан 7 November 2019 в 12:08
поделиться
Другие вопросы по тегам:

Похожие вопросы: