Подтвердить что ты не робот

Почему Erlang медленнее Java во всех этих небольших математических тестах?

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

Я был уверен, что в большинстве случаев Erlang работает быстрее из-за другой стратегии сбора мусора (за процесс), отсутствия общего состояния (чернил и процессов и процессов) и более компактных типов данных. Но я был очень удивлен, когда нашел сравнение Erlang vs Java math samples, где Erlang медленнее на несколько порядков, например. от x10 до x100.

Даже при одновременных задачах, как на нескольких ядрах, так и на одном.

Каковы причины этого? Эти ответы пришли на ум:

  • Использование примитивов Java (= > без кучи /gc ) для большинства задач
  • Одинаковое количество потоков в Java-коде и процессы Erlang, поэтому модель актера не имеет преимущества здесь.
  • Или просто, что Java статически типизирована, а Erlang не
  • Что-то еще?

Если это потому, что это очень специфические математические алгоритмы, может ли кто-нибудь продемонстрировать более реальные/практические тесты производительности?

UPDATE: у меня есть ответы до сих пор, суммируя, что Erlang не является подходящим инструментом для такого конкретного "быстрого Java-события", но то, что мне непонятно, - главная причина такой неэффективности Erlang: динамическая ввода, GC или плохого собственного компиляции?

4b9b3361

Ответ 1

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

Тем не менее, пусть немного отключится:
Если вы хотите программирование в стиле Эрланг в JVM, посмотрите Scala Актеры или Akka framework или Vert.x.

Ответ 2

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

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

Если вам действительно нужна тяжелая математика в Erlang, подумайте об использовании HiPE (подумайте об этом в любом случае).

Ответ 3

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

Но я хотел бы просветить еще один аспект - достоверность кода erlang (в некоторых случаях означает скорость развития), что легко можно было сделать, сравнив реализации эталонных тестов.

Например, k-нуклеотидный бенчмарк:
Версия Erlang: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=hipe&id=3
Версия Java: http://benchmarksgame.alioth.debian.org/u64q/program.php?test=knucleotide&lang=java&id=3

Если вы хотите больше реальных тестов, я бы предложил вам Сравнение С++ и Erlang для программного обеспечения Motorola Telecoms

Ответ 4

В решении Erlang используется ETS, Erlang Term Storage, которое подобно базе данных в памяти, работающей в отдельном процессе. В связи с тем, что он находится в отдельном процессе, все сообщения к этому процессу и из него должны быть сериализованы/десериализованы. Я бы подумал, что это будет причиной большой медлительности. Например, если вы посмотрите на тест "regex-dna", Erlang только немного медленнее, чем Java, и он не использует ETS.

Ответ 5

Я заинтересовался этим, поскольку некоторые из эталонных тестов идеально подходят для erlang, таких как секвенирование генов. Итак, http://benchmarksgame.alioth.debian.org/ первое, что я сделал, это посмотреть на реализации обратного дополнения, как для C, так и для Erlang, а также для деталей тестирования. Я обнаружил, что тест является предвзятым, потому что он не обесценивает время, затрачиваемое erlang на запуск VM/w планировщиков, изначально скомпилированный C запускается намного быстрее. Способ измерения этих показателей в основном: time erl -noshell -s revcomp5 main < revcomp-input.txt

Теперь в тесте указано, что Java заняло 1,4 секунды, а erlang/w HiPE занял 11. Запуск (Single threaded) кода Erlang занял у меня 0,15 секунды, и если вы снизили время, затрачиваемое на запуск vm, фактическая рабочая нагрузка заняла только 3000 микросекунд (0,003 секунды).

Поэтому я понятия не имею, как это оценивается, если это делается 100 раз, тогда это не имеет смысла, поскольку стоимость запуска виртуальной машины erlang будет равна x100. Если входной сигнал намного длиннее заданного, это имеет смысл, но я не вижу никаких подробностей на веб-странице этого. Чтобы сделать тесты более справедливыми для управляемых языков, попросите код (Erlang/Java) отправить сигнал Unix на python (который выполняет бенчмаркинг), чтобы он попал в функцию запуска.

Теперь, ориентируясь в сторону, erlang VM по существу просто выполняет машинный код в конце, а также виртуальную машину Java. Таким образом, в Эрланге математическая операция не займет больше времени, чем на Java.

То, что Erlang плохое, - это данные, которые необходимо часто мутировать. Например, цепочки блоков. Скажем, у вас есть символы "0123456789", теперь ваше шифрование xors содержит первые 2 символа на 7, затем xors следующие два символа в результате добавления первых двух, затем xors предыдущие 2 символа по результатам текущего 2 вычитаемого, затем xors следующие 4 символа.. и т.д.

Поскольку объекты в Erlang неизменяемы, это означает, что весь массив char необходимо копировать каждый раз, когда вы его мутируете. Вот почему у erlang есть поддержка вещей под названием NIFS, который является кодом C, на который вы можете позвонить, чтобы решить эту точную проблему. На самом деле все шифрование (ssl, aes, blowfish..) и сжатие (zlib,..), которые поставляются с Erlang, реализованы на C, также существует около 0 стоимости, связанной с вызовом C из Erlang.

Итак, используя Erlang, вы получаете лучшее из обоих миров, вы получаете скорость C с parallelism Erlang.

Если бы я смог реализовать обратное дополнение в FASTEST, я бы написал мутирующий код, используя C, но параллельный код с использованием Erlang. Предполагая бесконечный вход, я бы разделил Erlang нa > <<Line/binary, ">", Rest/binary>> = read_stream Отправляйте блок в первый доступный планировщик с помощью циклического цикла, состоящего из бесконечных скрытых узлов EC2 с частной сетью, добавляемых в реальном времени к кластеру каждые миллисекунды.

Затем эти узлы обращаются к C через NIFS для обработки (C была самой быстрой реализацией для обратного комплимента на веб-сайте alioth), затем отправляйте выходные данные мастеру node для отправки на вход.

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

Чтобы реализовать это в Java, мне пришлось бы писать однопоточный код, мне нужно было бы получить удар производительности при вызове с управляемого на неуправляемый (так как мы будем использовать реализацию C для работы с ворчанием, очевидно), то переписать для поддержки 64 ядер. Затем перепишите его для поддержки нескольких CPUS. Затем перепишите его снова для поддержки кластеризации. Затем перезапишите его снова, чтобы исправить проблемы с памятью.

И это Эрланг в двух словах.

Ответ 6

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

Было бы интересно проверить версию java с использованием флага -client и вложенных в бокс примитивов и сравнить это с erlang.

Я считаю, что использование hipe несправедливо, поскольку это не активный проект. Мне было бы интересно узнать, работает ли на нем какое-либо критически важное программное обеспечение.

Ответ 7

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

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