Может ли Java быть быстрее C++?
Есть у меня друг, Стас, с которым мы частенько, как настоящие программисты, особенно при наличии разных средств внутреннего подогрева, регулярно имеем традиционные пузомерки C++ (я) vs Java (он). Понятно, что социальная составляющая является основной в данных беседах, и, очевидно, полного конценсуса тут нет и быть не может, что и хорошо.
Но иногда, уже на трезвую голову, когда я думаю о подобном сравнении, при всем моем желании понять, почему Java в принципе может быть не то что быстрее, а хотя бы не медленнее C++, у меня не хватает аргументов даже для себя самого.
Для начала несколько “дано”:
- Мы сравниваем С++ 2011, компилируемый в машинный код, и обычную Java 7 (не real-time, embedded или что-то в этом роде), компилируемую в JVM-код, который только в процессе выполнения будет налету через JIT тоже компилироваться в машинный код.
- Допустим, компиляторы C++ и Java генерируют максимально эффективный код, насколько семантика языка позволяет оптимизировать.
Положим, A – это линейная скорость выполнения машинного когда. B – скорость компиляции байт-кода JVM в машинный код. Тогда общая скорость выполнения кода:
Очевидно, что B1 = 0 , так как С++ генерирует машинный код напрямую и не требует дополнительной работы в процессы выполнения. Но B2 стопроцентно НЕ ноль, так как каким бы эффективным не был компилятор JIT, он ВСЕГДА требует какого-то времени для компиляцию. Более того, JIT не компилирует все сразу, а “подкомпилирует” по мере прохождения путей выполнения. Получается, всегда есть ненулевая вероятность, что неожиданно придется выполнить код, ранее не требуемый, и потребуется время на его компиляцию. Даже если предположить, что компилятор JIT применяет изощренные способы предсказания путей выполнения и делает все, чтобы уменьшить B2 , но B2 по определению не 0. Если был бы 0, то не было бы JVM, а был бы чистый машинный код.
Далее, рассмотрим A1 и A2 . Эти параметры определяют, насколько эффективно компилятор создает код (или байт-код). По моему личному, субъективному и предвзятому мнению, у С++ (не С) больше шансов на оптимизацию благодаря шаблонам (компилятор имеет полноценную семантическую информацию для проведения inline’а) и генерация машинного кода под конкретную платформу (компилятор точно знает, какие машинные инструкции были бы максимально эффективны в каждом случае). Увы, я не особо силен в generic’ах Java, и руководствуюсь только слухами, что в Java они “ненастоящие”, добавленные гораздо позже и уступающие шаблонам C++. И так как компилятор обязан выдать стандартный переносимый JVM-код, то нет возможности оптимизировать под конкретную платформу. Есть надежда, что это сделает JIT, но там уже не будет семантической информации для более глубокой оптимизации. А еще JIT должен быть быстр, то есть будет компромисс между качеством оптимизации и скоростью компиляции. В С++ такой проблемы нет, так как компилировать можно как угодно долго.
Итак, это мои доводы для меня самого, измеренные в виртуальных попугаях. Не получается у меня убедить самого себя, что Java может быть быстрее или хотя бы на уровне с С++ по скорости. Буду рад за помощь в понимании этого вопроса.
Мы со Стасом проводили несколько несложных сравнений, в основном на реализации QuickSort, и Java по линейной скорости кода проигрывала где-то на 10%.
До C++ 2011 можно было говорить, у С++ нет модели памяти и стандартной библиотеки для потоков, поэтому у Java есть шанс выиграть на многопоточности, но сейчас у С++ все на месте. А подходы к многопоточности у С++ и Java, как мне кажется, одинаково неудобные (хотя std::async() – это очень сильная возможность), и им обоим далеко до goroutines в Go, actor’ов в Scala и т.д.
Понятно, что 10% не всегда делают погоду. Иногда важнее развитые инструменты интроспекции, среды разработки, контролируемое выполнение, замена кода налету и много другое, что дает платформа Java, и не дает “молотилка” C++. Но зачем говорить про скорость то?
Производительность C++ vs. Java vs. PHP vs. Python. Тест «в лоб»
/update/ Статья обновлена по результатам обсуждения. Поправлен код Python (около 40% ускорения), написан код на Perl и Ruby (но меня терзают смутные сомнения, что с ruby я что-то сделал неправитьно), поправлен код на Java (на моей машине корректнее тестировать int, а не long. к тому же int в Java эквивалентен long в C++).
Вопрос производительности (скорости работы) различных языков часто всплывает в комментариях, на форумах, часто необоснованные :). Встречаются статьи, в которых авторы приводят примеры, где выигрывает реализация на том или ином языке.
После прочтения очередной статьи мне захотелось самому разобраться «здесь и сейчас». Сначала захотелось сравнить Java и C++ (не верил я, что в вычислительных тестах ява может догнать и обогнать cpp). 10 минут и простой код на C++ и яве готов: простой цикл и математические операции. После написания теста подумал и перевёл их на php и python. Позже добавился код на perl и ruby.
Итак, пару слов о тесте:
Алгоритм синтетический, долгий цикл (двухуровневый) и в нём вычисление математического выражения. Таким образом оценивается вычислительная производительность самого языка (интерпретатора или скомпилированного кода), никаких привязок к качеству реализации тех или иных библиотек, никаких внешних сервисов, никаких системозависимых операций (диск, сеть, графика).
1) Мне нравится ява и я честно предполагал, что результаты будут лучше. Обновлено: long в 64-х битных системах работает значительно быстрее. При работе с int в 32-х битных системах Java значительно ускоряется (на моей машине быстрее, чем C++, видимо, JVM оптимизирует исполнение по умолчанию)
2) Я догадывался, что php будет медленней C++ и Java, но не думал, что он окажется быстрее Perl.
3) Предполагал, что Python будет сопоставим с PHP, но ошибся. Видимо, стандартная поставка PHP лучше оптимизирует исполнение кода.
4) Я совсем не знаком с Ruby, код взят из одного из комментариев. Причём использован код 1, так как у меня он работает быстрее чем код 2. Возможно, это также связано с тем, что у меня 32bit-система.
5) Я достаточно уважительно отношусь к различным языкам программирования, эта статья ни одним из углов не нацелена на разжигание холиваров. Каждый язык имеет свою нишу и своих поклонников.
Тесты запускались по 5 раз минимум, чтобы избежать случайных всплесков. Запускались из консоли и как «nice -n -9», то есть с максимальным на данный момент приоритетом в системе.
Чтобы не заставлять вас читать всю статью, сразу приведу краткие результаты.
Диаграмма (обновленная):
Старый вариант здесь
На диаграмме слолбец с Ruby частично прозрачен по причине того, что на моей машине скрипт Ruby исполнялся неприлично долго, в то время как в комментарии указано, что скрипт исполняется в 4 раза быстрее скрипта на Python — я в замешательстве.
Столбец с Python прозрачен, так как при включении psyco скрипт ускоряется более чем в 10 раз. Проверил на своей машине. Но это, с моей точки зрения, хак, не отражающий собственную производительность языка.
Столбец с PERL, как могут заметить старожилы, теперь идёт вровень с Python 2.6. Причиной этому послужила смена кода с C-подобного синтаксиса на использование range. Дополнительную производительность (около 12%) можно получить использовав директиву «use integer;», но это, по-моему, тоже хак.
Добавлен столбец с запуском Java-кода с ключём «-server». После перехода с «long» на «int» (повторюсь, int в java такой же как и long в c++ на 32bit-arch) он начал давать прирост в производительности почти вдвое.
Столбец с Ruby 1.9 на моём железе не тестировался, результат перенесён через сравнение с производительностью Python’а на той же машине.
И, чтобы не быть голословным, тестовый код.
Java, Test01.java (int в Java то же что и long в C++):
Python, Test01.py (вынос кода в функцию ускоряет работу кода почти вдвое, отдельная же инициализация range() на моей машине даёт порядка 5% производительности):
Perl, Test01.pl (обновлено, с range работает на 25% быстрее против c-подобного синтаксиса for):
Вот здесь приведён красивый пример на Perl, но, мне кажется, такой вариант уже слишком специфичен.
Вот здесь в комментариях обсуждают решение на erlang.
Как видите, ничего сложного: два цикла и математическое выражение. Вычислительная задача в чистом виде.
мой оригинал — там старая версия статьи, а также информация об версиях использованного ПО и результаты тестов из консоли.
Ещё раз повторюсь: каждый язык имеет свою нишу, своих поклонников и свои задачи, с решением которых он справляется лучше других.
PS: а вообще, нет смысла загоняться и меряться чем бы то ни было, производительность самого языка важна для достаточно узкого круга задач, т.к. в общем случае, системы, библиотеки и прочая обвязка нынче несоизмеримо тяжелее самой вычислительной задачи.
Когда Java быстрее C++ — сравнение производительности
Статья "Java vs C++ "Shootout" Revisited" опровергает бытующее мнение о низкой производительности Java-приложений. Приводятся результаты сравнения производительности, в котором на некоторых тестах Java ( Sun Java 1.4.2_01 ) выигрывает по скорости у C++ (GCC 3.3.1).
Re: Когда Java быстрее C++ — сравнение производительности
Нечем тут гордится что на C++ писать не умеют !

Re: Когда Java быстрее C++ — сравнение производительности
Абсолютно не объективный тест. Где соотношение количества ресурсов, которые отжирают для этих целей хоть клиентские, хоть серверные приложения java в сравнении с приложениями, закодированными на c++? опкод всегда будет быстрее java и это факт.

Re: Когда Java быстрее C++ — сравнение производительности
Гы гы гы. Оптимизированно написаный Java код работает быстрее чем неоптимально написаный C++ код :-). Реально мужик доказал только то, что человек, который умеет писать нормальный код. может этот код сделать быстрым :-). вне зависимости от платформы :-).

Re: Когда Java быстрее C++ — сравнение производительности
Если при кодировании после каждой строчки кода ставить строку for ( int i = 0 ; i < 65535; i ++); только тогда ява будет быстрее :)))

Re: Re: Когда Java быстрее C++ — сравнение производительности
> опкод всегда будет быстрее java и это факт. Ошибка ;-). Например вызов метода (особенно виртуального) в Java будет быстрее :-). Или например работа с RTTI в C++ на некоторых компиляторах может дать хорошую потерю производительности, а на Java все будет тип-топ :-). Много примеров, но суть в том, что дядька спец по Java, а вот в C++ он не шарит ;-).
Re: Когда Java быстрее C++ — сравнение производительности
Нда, на синтетических тестах действительно бывают такие приколы.
Re: Re: Когда Java быстрее C++ — сравнение производительности
>Если при кодировании после каждой строчки кода ставить строку for ( int i = 0 ; i < 65535; i ++); только тогда ява будет быстрее :)))
Только в том случае, если компилятор эту строчку не оптимизирует)
Re: Когда Java быстрее C++ — сравнение производительности
IMHO нюанс не в качестве кода, а в сборке мусора. С++ вызывает сборщик мусора для обьекта сразу, как тот перстал существовать. Java — как в голову придет.
В остальном код на C++ много эффективнее. Осталось придумать задачу, где требуется серьезная работа для сборщика мусора и С++ начнет проигрывать.
Re: Когда Java быстрее C++ — сравнение производительности
токо вот вопрос. а кто же писал оракловый инсталятор? И чего же он так тормозит? Может лохи писали? (хотя еще не проверял как работают проги под novm java, но думаю чудес не предвидится)
Re: Re: Когда Java быстрее C++ — сравнение производительности
А кто писал KDE? Чего оно тогда так тормозит (особенно при загрузке)?

Re: Re: Когда Java быстрее C++ — сравнение производительности
>С++ вызывает сборщик мусора для обьекта сразу, как тот перстал
>существовать.
Похоже я от жизни отстал. В какой из реализаций C++ появился garbage collector?
Re: Когда Java быстрее C++ — сравнение производительности
Статейка из разряда "На каких этапах наши паровозы быстрее гоночных болидов".Дурилка для маркетологов. Блин когдаж здохнет наконец этат утопия.
Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
верятно имелись ввиду деструкторы
а вот по поводу КДЕ. Думаю, если такую весч напишут на Жаба. будет пипец.

Re: Re: Когда Java быстрее C++ — сравнение производительности
> Блин когдаж здохнет наконец этат утопия.
Никогда. Ибо не утопия это, а весьма хорошая платформа :-).
Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> а вот по поводу КДЕ. Думаю, если такую весч напишут на Жаба. будет пипец.
Да ничего особенного не будет. Разницы ты не заметишь.

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>а вот по поводу КДЕ. Думаю, если такую весч напишут на Жаба. будет
>пипец.
Все будет нормально. Будет Java работать себе и память будет кушать. только что внизу оно будет на GTK или на QT написано. и все будет тип-топ.
Re: Когда Java быстрее C++ — сравнение производительности
Я не понимаю только одного, чтож вам Java как кость в горле? У неё своя ниша, свои задачи с которыми к слову говоря она прекрасно справляется. Мне вот у умников которые её ругают спросить хочется: а на чём они предлагают работать если нужна кроссплатформенность, серверная часть, не зависимость от БД? На С++ что ли? Или на Перле с Питоном? Давайте не будем бредить. То что Жава от релиза к релизу становится всё быстрее и удобнее по моему это всем на руку.
Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>>В какой из реализаций C++ появился garbage collector
ИМЗО имелось в виду освобождение памяти после того, как объект выходит из зоны видимости

Re: Когда Java быстрее C++ — сравнение производительности
> в котором на некоторых тестах Java ( Sun Java 1.4.2_01 ) выигрывает по скорости у C++ (GCC 3.3.1).
Нда, выбрали самый быстрый компилятор, да уж — ветку 3.4X пробовать не захотели.
Если сравнивать на тех областях, где либы явы быстрее, то тогда конечно. Тест совершенно не обоснованный и бессмысленный — пиар.
Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>>С++ вызывает сборщик мусора для обьекта сразу, как тот перстал
>>существовать.
>Похоже я от жизни отстал. В какой из реализаций C++ появился garbage
>collector?
Наверное, уважаемый eda вспоминал поговорку "чисто не там, где убирают, а там, где не мусорят" 🙂

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>ИМЗО имелось в виду освобождение памяти после того, как объект выходит
> из зоны видимости
Теперь остается только гадать :-).

Re: Re: Когда Java быстрее C++ — сравнение производительности
> Если при кодировании после каждой строчки кода ставить строку for ( int i = 0 ; i < 65535; i ++); только тогда ява будет быстрее :)))
Не, не совсем — если запустишь прогу на языке, в котором есть специально оптимизированные для предметной области средства, и на другом, более общего применения — естественно, результаты будут различными.
Спецязыки для этого и делают — для применения в своей области. А Java вообще сразу писали для embedded system. нда. :)))))))
Re: Re: Когда Java быстрее C++ — сравнение производительности
У Ораклового инсталятора JDK "Oracle JDK 1.1.7.30o (JDK 1.1.7B based)", потому и тормозит.

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>Наверное, уважаемый eda вспоминал поговорку "чисто не там, где
>убирают, а там, где не мусорят" 🙂
Да да да ;-).
Re: Re: Когда Java быстрее C++ — сравнение производительности
ММММ не расчехлился. причем сборщтк мусора и С++ . Мусорщик — есть примочка ВМов. Хотя конечно если мусорщиком считать free() ?! То вряд ли гарбаж коллектор (мля слово то какое) тут вряд ли сие обскачет

Re: Re: Когда Java быстрее C++ — сравнение производительности
> IMHO нюанс не в качестве кода, а в сборке мусора. С++ вызывает сборщик мусора для обьекта сразу, как тот перстал существовать. Java — как в голову придет.
Это тоже верно — если сборщик ни разу не запустится, то потом система просто пометит память как пустую, одним махом, и скорость будет приличной :)))) Чем каждый раз вызывать деструктор, который объявлен например, но ничего не делает.
Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> Это тоже верно — если сборщик ни разу не запустится, то потом система просто пометит память как пустую, одним махом
"Потом" — это после выключения компьютера чтоли 🙂 ?

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> "Потом" — это после выключения компьютера чтоли 🙂 ?
В самую точку! После завершения работы программы — когда VM выключат :))))

Re: Когда Java быстрее C++ — сравнение производительности
Ну если делать так:
if (++this->counter >= this->count_max)
Toggle *toggle = new Toggle(val);
for (int i=0; i<n; i++) <
val = toggle->activate().value();
>
cout << ((val) ? "true" : "false") << endl;
delete toggle;
вместо того чтобы разместить toggle на стеке, то конечно C++ окажется медленнее. Вообще во всём этом "сравнении производительности" чувствуется явно предвзятое отношение к C++ и код на последнем подгоняется под код на джаве.
Re: Re: Когда Java быстрее C++ — сравнение производительности
> вместо того чтобы разместить toggle на стеке, то конечно C++ окажется медленнее.
Как насчет того, что в Java объекты всегда создаются именно способом "Toggle toggle = new Toggle()" ? Вроде ж нет априорного преимущества перед C++?
Re: Re: Когда Java быстрее C++ — сравнение производительности
> око вот вопрос. а кто же писал оракловый инсталятор? И чего же он так тормозит? Может лохи писали? (хотя еще не проверял как работают проги под novm java, но думаю чудес не предвидится)
Оракл гордится своими старыми jdk. Замечательный пример — jdk 1.1.8.113, стоявший у нас на работе =)))
Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>>С++ вызывает сборщик мусора для обьекта сразу, как тот перстал
>>существовать.
>Похоже я от жизни отстал. В какой из реализаций C++ появился garbage collector?
Вот честно, не знаю. Завершение жизни обьекта в JAVA устроено иначе. Цитировать книжки Java не хочеться, а в моей голове без практики ничего не задерживаеться ;-).
Могу приврать, но в Java можно как-то оживить умерший обьект, до которого не дошли руки сборщика мусора. Так что есть некоторый маневр и в этом.
А какие РЕАЛЬНЫЕ идеи есть по поводу этого теста ? Байт код не может выполняться быстрее чем машкод.
Эффективность сборки мусора, единственное, что пришло в голову.
Re: Когда Java быстрее C++ — сравнение производительности
Не забывайте ставить ссылки на первоисточник текста новости .

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
2 eda:
> а в моей голове без практики ничего не задерживаеться ;-).
Угу. Все, кому надо уже поняли :-).

Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> Мусорщик — есть примочка ВМов.
В корне не верно :-). Но в C++ его-таки нативного нет и быть не может ;-).

Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
Я о том и говорю, что в java объекты создаются исключительно в куче, тогда как в C++ их можно создавать и на стеке и это зачастую (и уж точно в данном конкретном случае) гораздо быстрее. Код на C++ подгонялся под java, а не наоборот.
Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
>А какие РЕАЛЬНЫЕ идеи есть по поводу этого теста ? Байт код не может >выполняться быстрее чем машкод. >Эффективность сборки мусора, единственное, что пришло в голову.
Повторить! Что-он попутал. гадом буду!
Re: Re: Когда Java быстрее C++ — сравнение производительности
> for ( int i = 0 ; i < 65535; i ++);
я долго думал, почему именно "65535" ?? это ведь 2^16-1, а int, наскоко мне известно (даже более того — я в этом уверен) — 4-х байтовый. (по крайней мере в нормальных системах — aka linux))
Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> Вот честно, не знаю. Завершение жизни обьекта в JAVA устроено иначе.
> Эффективность сборки мусора, единственное, что пришло в голову.
Способность к аналитическому мышлению — очень хорошее качество, но в данном случае оно вас несколько подвело: в C++ нет "легализованного" сборщика мусора. Оговорки: под сборкой мусора мы понимаем автоматическое (без участия человека) освобождение неиспользуемой памяти в куче; существующим для C++ "third-party" реализациям сборщиков мусора мы выражаем наше почтение, но не считаем их частью стандартной технологии.
> Могу приврать, но в Java можно как-то оживить умерший обьект, до которого не дошли руки сборщика мусора. Так что есть некоторый маневр и в этом.
Вы не приврали, получить ссылку на объект после освобождения всех иных ссылок можно. Но непонятно, в чем тут "маневр".

Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> А какие РЕАЛЬНЫЕ идеи есть по поводу этого теста ? Байт код
> не может выполняться быстрее чем машкод. Эффективность сборки
> мусора, единственное, что пришло в голову.
Вообще-то на этот вопрос должен был ответить сам автор "исследования". И то, что он такого ответа не дал ещё раз подчеркивает его "ценность".

Re: Когда Java быстрее C++ — сравнение производительности
я где-то бенчмарк компайлеров видел — там идея та же: Жаба рулит.
но даже там на графиках видно, что тригонометрия /да и не только — всё что связано с фпу/ нуууу оооочень тормозииит.

Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> 4-х байтовый. (по крайней мере в нормальных системах — aka linux))
4 байта = 32 бита (i386), на 64 битной системе инт буит 8 байт занимать.
Re: Когда Java быстрее C++ — сравнение производительности
hash.cpp: for (int i=1; i<=n; i++)
ясно понятно что X[a]=.. гораздо медленей чем просто ht.put в java и X.insert в с++
Re: Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
> Я о том и говорю, что в java объекты создаются исключительно в куче, тогда как в C++ их можно создавать и на стеке и это зачастую (и уж точно в данном конкретном случае) гораздо быстрее. Код на C++ подгонялся под java, а не наоборот.
Кстати, много ли вы в этих тестах увидели операторов ‘new’ (я о C++ коде) ? Я вот ткнулся наудачу в несколько файлов и ни одного не обнаружил. Если кому интересно, где исходники, ходите сюда:

Re: Re: Re: Когда Java быстрее C++ — сравнение производительности
2 nelapsi:
"О сколько нам открытий чудных. "
>а int, наскоко мне известно (даже более того — я в этом уверен) — 4-х
>байтовый.
Ты абсолютно не прав. int — размером в маш. слово. а оно может быть 1/2/3/4/5/6/7/8/9 байт. В зависимости от платформы :-). Думаешь для чего в кроссплатформенных аппликухах введены типы int16/int32 итд? 😉