Что быстрее, Clojure или ClojureScript (и почему)?

Если бы я должен был догадаться, я уверен, что ответ будет Clojure, но я не уверен, почему. Логически (мне) кажется, что ClojureScript должен быть быстрее:

Оба являются "динамическими", но ClojureScript

  • Компиляция с JavaScript, работающая на V8
  • Двигатель V8, возможно, является самым быстрым динамическим движком языка.
  • V8 записывается в C

тогда как Clojure:

  • Также динамический
  • Работает в JVM, у которого нет встроенной динамической поддержки, поэтому я думаю, что JVM должен делать то, что делает V8, чтобы включить динамическую поддержку.
  • и Java медленнее, чем C

Итак, как Clojure быть быстрее, чем ClojureScript? "Динамический" означает что-то другое, если говорить, что JavaScript динамический, а Clojure - динамический? Что я не вижу?

(Конечно, если ClojureScript действительно быстрее, то верно ли это рассуждение выше?)

Я думаю, что компиляция Clojure.... является, по крайней мере, частью вопроса. Я знаю, что часть JVM не может просто быть простым интерпретатором (иначе ClojureScript будет быстрее), но Clojure не может скомпилировать обычный байт-код, так как в JVM нет "динамического". Итак, какова разница между тем, как компилируется/выполняется ClojureScript и каким образом Clojure компилируется/исключается и как выполняется компиляция/выполнение простой Java, а также различия производительности в каждом?

Ответы

Ответ 1

Этот вопрос трудно ответить точно, без ссылки на конкретную контрольную задачу (или даже конкретные версии Clojure или ClojureScript).

Сказав, что в большинстве случаев я бы ожидал, что Clojure будет несколько быстрее. Причины:

  • Clojure обычно сводится к статическому коду, поэтому он не выполняет никаких динамических запросов во время выполнения. Это очень важно: высокопроизводительный код часто создает байт-код, который очень похож на статически типизированную Java. Вопрос заключается в том, что ложное предположение заключается в том, что динамический язык должен выполнять динамические поиски методов во время выполнения: это не всегда так (и обычно это не в Clojure)
  • JVM JIT очень хорошо спроектирован, и я считаю, что в настоящее время он по-прежнему немного лучше, чем JIT для JavaScript, несмотря на то, насколько хорош V8.
  • Если вам нужно concurrency или вам нужно использовать несколько ядер, то, очевидно, нет конкурса, поскольку JavaScript однопоточный.....
  • Компилятор Clojure более зрелый, чем ClojureScript, и в последние годы он довольно много работал с настройкой производительности (включая такие вещи, как примитивная поддержка, протоколы и т.д.).

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

И более принципиально, ваш выбор между Clojure и ClojureScript не должен касаться производительности в любом случае. Оба они обладают непревзойденными преимуществами производительности. Основным решающим фактором должен быть:

  • Если вы хотите запускать в Интернете, используйте ClojureScript
  • Если вы хотите запускать на сервере в среде JVM, используйте Clojure

Ответ 2

Собственно, V8 написан на С++. Тем не менее, в основном это то же, что и JVM, а JVM написано на Javascript-коде C. V8 JIT и выполняет код JIT'd. Аналогично JVM JIT компилирует (или компилирует hotspot) байт-код (NOT Java) и выполняет этот сгенерированный код.

Bytecode не является статическим, как Java. На самом деле это может быть довольно динамично. Java, с другой стороны, в основном статична, и неверно связывать Java с байт-кодом. Компилятор java преобразует исходный код Java в байт-код, а JVM выполняет байт-код. Для получения дополнительной информации я рекомендую вам посмотреть блог Джона Роуза (пример). Там много хорошей информации. Кроме того, попробуйте искать переговоры с помощью Cliff Click (например этот).

Аналогично, код Clojure напрямую компилируется в байт-код, а JVM выполняет тот же процесс с этим байт-кодом. Компиляция Clojure обычно выполняется во время выполнения, что не является самым быстрым процессом. Аналогично, перевод Clojurescript в Javascript также не является быстрым. V8 перевод Javascript в исполняемую форму, очевидно, довольно быстр. Clojure может быть досрочно скомпилирован в байт-код, и это может устранить много издержек запуска.

Как вы сказали, также неверно сказать, что JVM интерпретирует байт-код. Выпуск 1.0 сделал это более 17 лет назад!

Традиционно существовали два режима компиляции. Первый режим - это компилятор JIT (Just in Time). Где байт-код переводится непосредственно в машинный код. Компиляция Java JIT выполняется быстро и не генерирует высоко оптимизированный код. Он работает нормально.

Второй режим называется компилятором hotspot. Компилятор hotspot очень изощрен. Он запускает программу очень быстро в интерпретируемом режиме и анализирует ее по мере запуска программы. Поскольку он обнаруживает горячие точки (пятна в коде, которые выполняются часто), он будет скомпилировать их. В то время как компилятор JIT должен быть быстрым, потому что ничего не выполняется, если только JIT'е компилятор hotspot не может позволить себе потратить дополнительное время, чтобы оптимизировать сокет из кода, который он компилирует.

Кроме того, он может вернуться и снова вернуться к этому коду и применить к нему еще больше оптимизаций, если это необходимо и возможно. Это тот момент, когда компилятор hotspot может начать бить скомпилированный C/С++. Поскольку он имеет представление о времени выполнения кода, он может позволить применять оптимизации, которые статический компилятор C/С++ не может сделать. Например, он может встроить виртуальные функции.

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

Недостатком точки доступа является то, что она начинает немного медленнее. Одним из изменений в JVM Java 7 было объединение компилятора JIT и компилятора hotspot. Однако этот режим является новым, и он не является стандартным, но как только начальный запуск должен быть хорошим, а затем он может начать расширенную оптимизацию что JVM так хорош.

Ура!

Ответ 3

Это не столько ответ, сколько исторический комментарий: как HotSpot VM, так и движок V8 js могут быть истолкованы в проекте Self в Sun Microsystems, который, как я думаю, прототипировал многие технологии, которые позволяют им работают так же быстро, как и они. Что-то нужно учитывать при сравнении их обоих. Я бы разместил это как комментарий, но система репутации не позволила мне.