До JIT изначально Java была медленной, но сегодня производительность довольно близка к C++. Я хочу знать, проводил ли кто-нибудь измеримое сравнение производительности между двумя языками? Чем Java уступает C++? Java обеспечивает значительный прирост производительности для разработчиков, поэтому они могут писать приложения намного быстрее из-за мусорного колледжа, отсутствия указателей и т.д. 100% Java, возможно, в два раза, но разработчики по-прежнему выбирают C / C++ из соображений производительности. Может ли кто-нибудь продемонстрировать, где нельзя заставить Java работать так же хорошо, как C++ для приложений, подобных тем, о которых я упоминал.
Позвольте мне просто добавить, что большая часть работы с приложениями все еще выполняется на C++ по определенной причине. Это более чем субъективный вопрос. Языки с более высоким уровнем абстракции часто снижают производительность. Если бы этого наказания не существовало, мы бы все программировали на языках более высокого уровня. Чем все еще выгодна Java по сравнению с C++? Быть конкретной.
Может быть, это немного отвлекает, но ... «Основные проблемы нашей работы не столько технологические, сколько социологические по своей природе» -Peopleware. «Мой язык быстрее твоего» будет продолжаться до скончания веков. Я бы предпочел спросить ... что разработчикам наиболее удобно и будет ли этого достаточно?
«... чтобы они могли писать приложения намного быстрее из-за мусорного колледжа». Да, этот колледж действительно улучшает твои навыки программирования. Я видел, как мусорщики делают какие-то гадости на своих компьютерах. Но только тех, кто закончил мусорное училище, конечно :-)
Я думал, что к субъективным и аргументированным вопросам относятся неодобрительно? Мне кажется, ОП уже решил, что Java лучше. В любом случае, как бы вы не хотели это признавать, производительность и надежность повышаются с обеих сторон. Управление ресурсами на Java без надлежащего RAII - это боль.
Джальф, я выделил вопрос жирным шрифтом. Я решил, что Java медленнее, чем C++, по крайней мере, текущая реализация. Теперь вопрос в том, почему.




Во многом это похоже на сравнение яблок с апельсинами.
C++ основан на представлении о том, что вы не платите ни за что, чем не пользуетесь. Если вы сами управляете памятью, если не используете виртуальные функции и т. д.
Java не дает вам такой свободы. Он дает вам функции, которые вам, возможно, даже не нужны. Как бы то ни было, вы можете захотеть выделить память самостоятельно, вам придется использовать объекты кучи для всего, поэтому вы получите влияние на сборку мусора.
Как только вы начнете говорить о графических интерфейсах, сравнение станет еще более трудным, поскольку разные инфраструктуры пользовательского интерфейса и наборы инструментов имеют разные проблемы с производительностью. Например, Swing / AWT обычно будет медленнее, чем что-то, написанное непосредственно для собственной ОС. В C++ вы редко найдете действительно переносимый инструментарий и т. д.
Я думаю, что когда разработчики начали openoffice, Java была намного медленнее, а инструменты пользовательского интерфейса были медленными и некрасивыми. Такие инструменты, как Eclipse, доказывают, что вы можете создавать относительно хорошие пользовательские интерфейсы даже на Java, хотя, по общему признанию, SWT - это набор инструментов, который делает много вещей на нативном уровне.
Вы можете выделить память самостоятельно - просто выделите хороший большой массив байтов и раздайте ему индексы. Это будет неприятно (у вас не будет типов), но вы можете написать свой собственный подраспределитель, если вам действительно очень нужно.
Если у вас нет типов, которые вряд ли дадут вам возможность самостоятельно управлять памятью, не так ли?
Барри, я имел в виду выделить объекты ... Не уверен, что вы действительно можете сделать с просто старым добрым массивом ...
Я не верю, что кто-то сможет доказать, что C++ всегда будет значительно быстрее, чем Java, по той простой причине, что вы всегда можете вернуться к JNI, чтобы получить собственную скорость от Java.
См., Например, SWT - графические инструменты, созданные IBM (я думаю), предназначенные для замены Swing и обеспечения как собственной производительности, так и внешнего вида.
Я, со своей стороны, предпочел бы простоту разработки скорости, поскольку считаю минимальное время разработки более важным, чем исходная скорость приложения, особенно когда я все еще могу получить эту скорость - я могу получить и простоту разработки Java с скорость компилируемых языков.
C++ всегда будет быстрее C++?
Хорошая уловка, сейчас исправлено, но, по крайней мере, вы не могли придраться к правдивости утверждения :-)
Потому что, как только вы это прочитали, его производительность увеличилась на единицу? :)
Чтобы завершить ответ Пакса и Ури, вот несколько тестов недавний:
Как уже говорилось, это два очень разных языка, и некоторые убеждены, что Java когда-нибудь будет медленнее C++ из-за:
[Юмор]
"Java is high performance. By high performance we mean adequate. By adequate we mean slow." Mr. Bunny
Как упоминалось дрибес в комментариях, выделение кучи не является хорошим аргументом. В этом "Легенды городского перформанса, заново" упоминается:
"Garbage collection will never be as efficient as direct memory management." And, in a way, those statements are right -- dynamic memory management is not as fast -- it's often considerably faster.
The malloc/free approach deals with blocks of memory one at a time, whereas the garbage collection approach tends to deal with memory management in large batches, yielding more opportunities for optimization (at the cost of some loss in predictability).
- Выделение памяти в Java почти бесплатное (около 10 машинных инструкций), и сборщик мусора требует затрат только на живые объекты, поэтому первый пункт неверен.
Люди не должны спорить о вещах, которых они не знают. Распределение кучи, динамическое приведение ... Очень документированный и очень объективный ответ. Это иронично.
dribeas: Все не так просто. 10 инструкций, а что дальше? Все ваши объекты волшебным образом собраны в сборку мусора? Как насчет накладных расходов, необходимых для обеспечения возможности сборки мусора? Объекты должны хранить больше данных, что удорожает их инициализацию, что-то должно определять, когда запускать сборщик мусора и так далее.
@Jalf: Конечно. Ограничения Java GC являются причиной того, что он работает в 17 раз медленнее, чем F# в этом тесте: fsharpnews.blogspot.com/2010/05/java-vs-f.html
Я провел собственное сравнение производительности: edval.biz/benchmarking-java-versus-c-with-astar на небольшой, но все же значительной программе, загружающей процессор. Удивительно, но я обнаружил, что Java на 30% быстрее. Поскольку я давно фанат C++ и эксперт по C++, я очень старался изменить результаты. Однако после довольно всесторонних экспериментов я считаю, что Java работает быстрее. Причина может заключаться в неспособности оптимизирующих компиляторов C++ предполагать «отсутствие псевдонимов». Если вы мне не верите, скачайте мой исходный код или попробуйте сами.
Для меня этот вопрос - отвлекающий маневр (возможно, не намеренно). Это действительно неправильный вопрос.
Первые вопросы, которые нужно задать, - это
Вот несколько хороших вопросов "почему"
Я подозреваю, что вам действительно нужно сначала сосредоточиться на аспектах пerformance вашей программы (с большой буквы), а не на аспектах пerformance (маленькая буква «p»). Если вы можете добраться до точки, где язык мешает, значит, вы проделали действительно хорошую работу в отношении производительности.
Для нового кода - важно заранее спланировать производительность и эффективность. Я всегда рекомендую, чтобы производительность и эффективность рассматривались так же, как и любая другая функция (они являются функциями): так же, как UI bling или надежность. Конечно это будет зависеть от многих вещей, но когда это важно, вам нужно спланировать это заранее:
Причина, по которой я думаю, что это отвлекающий маневр, заключается в том, что редко можно просто выбирать между C++ и Java - это очень, очень разные языки с очень разным временем выполнения. Я подозреваю, что обычно у вас есть другие ограничения, которые так или иначе подталкивают вас - это будут факторы более высокого порядка, чем производительность языка. Вычислимость с существующим кодом, навыки и опыт существующих сотрудников и т. д. И т. Д.
Окружающая среда тоже имеет значение. Например, Java почти никогда не будет правильным выбором для клиентских приложений (в отличие от веб-приложений). И наоборот, нативный C++ почти никогда не станет выбором для веб-приложений. (обратите внимание, я парень, работающий с окнами - в * nix ситуация может быть очень другой).
Компиляторы JIT могут работать быстрее для многих отдельных конструкций кода, поскольку они могут использовать профилирование кода во время выполнения.
Например, VonC в своем ответе на этот вопрос упоминает выделение кучи для всех объектов. На самом деле это не так: JIT может размещать объекты в стеке, если он может доказать с помощью анализ побега, что ссылки на объект не переживут кадр стека. Таким образом, компилятор может получить преимущество в производительности за счет выделения стека, в то время как программист может быть уверен в безопасности предполагаемого выделения кучи GC.
Точно так же Ури упоминает виртуальные функции (называемые виртуальными методами в большинстве языков, отличных от C++). Это еще один случай, когда у JIT-компиляторов есть преимущество, которое почти никогда не доступно для опережающих компиляторов (AOT): JIT может вставить встроенную проверку дешевого типа (сравнение разыменованных слов) и фактически встроить вызов виртуального метода, если этот конкретный сайт вызова оказывается мономорфным (т.е. на практике фактический тип всегда один и тот же). Оказывается, что на практике до 95% всех вызовов виртуальных методов являются мономорфными, так что это может быть довольно большой выигрыш - и это выигрыш, которым сложно воспользоваться компиляторам AOT, поскольку загрузка кода времени выполнения может динамически изменять характеристики времени выполнения.
Это 80% число составлено? Я предполагаю, что если бы оно было действительно таким высоким, кодер использовал бы виртуальные функции для вещей, для которых они не должны использоваться ...
Нет, это не так. Я получил его от Azul's Cliff Click (ранее Sun и архитектор сервера HotSpot). Я добавил ссылку на атрибуцию - ищи цифру 95% (на самом деле она была выше, чем я запомнил).
Обратите внимание, что он говорит о Java, которая по умолчанию использует виртуальные методы, то есть намного больше, чем большинство других статически типизированных языков (но по теме вопроса).
Теоретически, в зависимости от того, как среда выполнения C++ реализует свой RTTI, можно было бы выполнять такую же проверку поиска в кеше для всех виртуальных вызовов. Это не что-то особенное для JIT-компиляторов. Я неправильно понял принцип, описанный в вашем сообщении, но я определенно вижу, что это приносит пользу.
Это не так просто, Грег. Подход, специфичный для Azul, использует толстые 64-битные указатели со встроенной информацией о классе, так что даже косвенное обращение не требуется. Точно так же он работает для динамически загружаемого кода, что является нетривиальным преимуществом для обслуживания в серверном коде.
Подход разрешает встраивание среды выполнения через границы обслуживания, так что сторонние библиотеки, для которых у вас может даже не быть исходного кода, могут иметь встроенный в них код, даже если вызов является виртуальным.
Я думал, что анализ побега был плановой оптимизацией. В каких версиях ВМ это реализовано? Может быть, я запутался, что это было не раньше Java 7.
Еще одна скамейка: перестрелка
За вас не проголосуют, потому что ваша ссылка доказывает, что Java медленнее, чем C++
Java медленнее C++. Вот почему я задал вопрос. Теперь вопрос конкретно в том, где Java медленнее?
Некоторые вещи лучше строить с помощью Java, C# или любых языков управляемого программирования. В остальном всегда будет лучше строиться на неуправляемом языке программирования (например, C или C++).
Первая категория обычно включает «приложения» в целом, а вторая категория обычно включает «платформы» в целом.
Создание FireFox или WebKit на Java не только просто глупо, но и приведет к тому, что конечный продукт станет действительно очень медленным, плохим и потратит много ресурсов для конечных пользователей. Open Office, возможно, является хорошим кандидатом для Java, C# или Болтовня в этом отношении. Но создавать FireFox или WebKit на Java (или C#, если на то пошло) просто глупо и является гарантией отказа ...
C++ и C будут на несколько порядков быстрее для многих вещей, кроме того, они будут использовать часть памяти. Просто так оно и есть. И пока Java и C# являются «управляемыми» языками программирования, это никогда не изменится. Может быть, когда-нибудь процессоры станут настолько быстрыми, что «это не имеет значения». Но я сомневаюсь в этом, поскольку люди склонны сгибать свои требования по мере увеличения количества ЦП ...
Если вы хотите создать браузер, извините, но вам нужно научиться C или C++;)
У языков нет скорости. Ни в спецификациях языка Java, ни в C++ не указано, «и программы должны быть скомпилированы для обеспечения эффективности это».
Каждый язык определяет список того, что программа должна делать, или, по крайней мере, кажется, делает, который в некоторых случаях устанавливает верхнюю границу того, насколько эффективной может быть программа, но часто умный компилятор может игнорировать эти правила в отдельных программах, потому что все важно то, что программа ведет себя будто, в соответствии со спецификацией. Функции могут быть встроены, данные кучи могут быть перемещены в стек и так далее.
Производительность программы зависит от трех вещей: компилятора, базовой платформы / оборудования и самого программного кода.
Не «язык». Самое близкое, что вы получаете, - это компилятор.
Есть веские причины, по которым один из языков может быть быстрее другого. C++ дает меньше обещаний, которые потенциально могут замедлить выполнение программы, но Java JIT'ed, что означает, что он потенциально может использовать информацию времени выполнения для оптимизации кода, что C++ не может легко сделать ... И опять же, нигде в в спецификации говорится, что C++ должен быть изменен нет. Точно так же, как я считаю, есть также компиляторы Java, которые генерируют собственный код вместо байт-кода JVM.
Ваш вопрос имеет смысл только в том случае, если у вас есть конкретный компьютер, на котором вы работаете, определенный компилятор для каждого языка и конкретная реализация вашей программы на каждом языке, в этом случае вы можете просто запустить оба, чтобы увидеть, какой из них самый быстрый.
Сборка мусора - еще один замечательный пример. Конечно, сборка мусора подразумевает некоторые накладные расходы, но также позволяет использовать некоторые важные ярлыки. Выделение кучи смехотворно дешево в управляемых языках, таких как Java или .NET, потому что управляется и собирает мусор. В C++ это… не указано, конечно, но на практике обычно очень медленно, потому что ОС должна пройти через кучу, чтобы найти свободный блок памяти в более или менее фрагментированном пространстве памяти. Какой самый быстрый? Зависит от ОС. Зависит от компилятора. Зависит от исходного кода.
Исходный код также имеет большое значение. Если вы возьмете программу на Java и наивно перенесете ее на C++, она будет работать как дерьмо. C++ не так хорошо справляется с виртуальными функциями и обычно предлагает лучшие альтернативы, которые вы могли бы использовать вместо этого. Выделение кучи может быть очень медленным в C++, поэтому, опять же, наивное повторное выполнение программы Java было бы крайне неэффективным. То же самое и в обратном направлении. Многие идиомы C++ были бы излишне медленными при прямом переносе на Java. Итак, даже если вы остановились на одной платформе и одном компиляторе, как вы сравните производительность своей программы? Чтобы даже передать его компилятору, вам нужно написать две его реализации, и тогда это уже будет не та же программа.
Тем не менее, я думаю, будет справедливо сказать, что на большинстве современного оборудования с современным компилятором Java и современным компилятором C++ можно реализовать большинство программ, которые будут очень эффективными и, безусловно, достаточно быстрыми. Но только если вы понимаете язык, на котором работаете, и играете по его правилам. Если вы попытаетесь написать Java-код на C++, Java по волшебству окажется намного эффективнее, и наоборот.
Думаю, самый краткий ответ на ваш вопрос - «Нет. Никто не может количественно оценить разницу в производительности между C++ и Java»;)
+1, я писал ответ в этих строках, но не близко к этому сообщению
Очень хороший! Хотя я не совсем согласен, я все же поставил ему +1;)
+2 за ответ, -1 за преувеличения насчет кучи и виртуальных функций C++ = +1
Это не преувеличение. Куча работает очень медленно по сравнению, скажем, с кучей .NET (которая, по сути, представляет собой просто операцию проталкивания в стек. Распределение кучи C++ может включать в себя переключение контекста, а также обход связанного списка. Это может быть несколько порядков величины. помедленнее.
И я не вижу преувеличений в виртуальных функциях. Java может удалить их во время выполнения, C++ не может (если вы не реализуете JIT или модификацию кода времени выполнения). Это означает, что C++ больше страдает от виртуальных машин, чем Java. Если вы сделаете все виртуальным, как в Java, вы это почувствуете.
-1: Все знают, что сложно делать общие выводы о производительности Java и C++ по всем программам, но меня расстраивает то, как люди перестают пытаться. Это простой вопрос, и многим людям нужно получить какие-то рекомендации по этому вопросу. На самых популярных компиляторах / платформах, на больших программах, включающих множество алгоритмов, что является хорошим практическим правилом или, по крайней мере, набором точек данных (т. Е. Тестов)?
Настоящим я делаю запись: я считаю, что независимые тесты на популярных платформах показывают, что Java примерно в два раза медленнее, чем C++, в больших программах. В небольших программах (микробенчмарках) Java все еще в среднем в два раза медленнее, но с очень большими вариациями.
@ Тим: Речь идет не об обобщении производительности по всем программам, а по всем программам, компиляторам и компьютерам. И дело не в том, чтобы «сдаться», а в том, чтобы понять, что ответ бесполезен, и нет простого хорошего практического правила.
Я думаю, что в реальном мире (реальные приложения делают реальные вещи) хорошо написанный C / C++ превосходит управляемые языки. Да, это правда, теоретически распределение кучи в gc обходится дешево. Однако грамотный разработчик C++ не стал бы все складывать в кучу!
+1: Хорошее объяснение языкового сравнения в целом; -1: Куча в C / C++ управляется в пользовательском пространстве, поэтому она так же эффективна, как и куча Java; -1: вызов виртуальных функций в C++ выполняется так же быстро, как и использование указателя на функцию. Кроме того, вызывающие программы также встроены в большинство оптимизирующих компиляторов, поэтому Java может работать не лучше, чем C++, и обычно медленнее.
Куча в C++ не сжимается, как в Java / .NET, а это означает, что найти блоки памяти для выделения намного дороже. Виртуальные функции примерно так же дороги, как указатели на функции, да (на самом деле, есть еще один уровень косвенного обращения к виртуальным функциям, но он достаточно близок), но я никогда не говорил, что указатели на функции также работают быстро.
А в C++ виртуальные функции часто встроены в нет, потому что во время компиляции обычно трудно увидеть, какая функция будет вызвана (если бы можно было вызвать только одну функцию, вы, вероятно, не сделали бы функцию виртуальной). И да, Java может быть быстрее C++. Так что же -1;) почему так много программистов считают религиозным вопросом: «С ++ всегда должен быть самым быстрым, верно? Верно?
Некоторые моменты, которые следует учитывать:
Если вы получите лучший компилятор C++, ваш код не станет быстрее. Сначала вам нужно перекомпилировать его. Если вы получите лучшую JVM, весь ваш Java-код будет работать быстрее
Если вы получите лучший компилятор C++ / JVM, вы увидите на 10-20% более быстрое выполнение, обычно в крайних случаях. Если вы найдете лучший алгоритм для достижения того, что вам нужно, вы легко сможете получить на 1000-10 000% больше производительности, а иногда даже больше.
Итак, сегодня, если производительность является проблемой, вам следует обратить внимание на эти два факта:
Все остальное - просто FUD.
Многие забывают, что методы JIT можно применять к любым двоичным файлам, даже к тем, которые создаются компилятором C++. Большинство преимуществ JIT-компиляции для Java также справедливы для C++, если вы используете что-то вроде HP Dynamo (эмулятор, который запускает исполняемые файлы быстрее, чем собственный чип, на котором он работает и эмулирует). Профилирование времени выполнения на самом деле является преимуществом не Java в производительности, а JIT-компиляции в целом.
Я реализовал чувствительные к производительности приложения (физическое моделирование, финансовые модели) как на C, так и на Java. Реальность такова, что я всегда получал гораздо больший выигрыш в производительности за счет изменения алгоритмов, чем за счет настройки реализации, но реализация также имеет значение. На данный момент я считаю, что Java работает медленнее, чем C (у меня нет такого большого опыта работы с числами в C++), но многое можно получить путем тщательной настройки, и эта настройка намного проще в Java, поскольку вы не нужно иметь дело с ошибками сегментации, двойным освобождением и т. д. C++ занимает здесь среднее место, поскольку современные методы C++ (интеллектуальные указатели, шаблоны, контейнеры STL) предлагают как скорость, так и относительную безопасность использования.
У приложений Java есть накладные расходы на инициализацию, которых нет у программ C++. При использовании JIT они не так оптимизированы на микроуровне, как программы на C++. Кроме того, есть небольшие накладные расходы времени выполнения (сборщик мусора + непрямые накладные расходы). В целом, эти измеримые различия не имеют большого значения. Но...
Хорошо известно, что когда приложение Java запускается впервые, оно должно активировать свой конденсатор потока, чтобы вернуть среду в состояние 1995 года. Это вносит небольшую задержку при запуске. Но как только это закончится, JVM будет работать примерно так же, как сопоставимая программа C++, работающая на оборудовании с 1995 года.
Where does Java fall short when compared to C++?
Отличный вопрос. Java и JVM имеют два основных недостатка, снижающих производительность по сравнению с C++:
Обобщения, основанные на стирании типа.
Отсутствие ценностных типов.
Первое означает, что общий код требует упаковки и распаковки, что влечет за собой огромное количество ненужного выделения и дополнительные уровни косвенного обращения, которые недружелюбны к кешу.
Последнее означает, что программист не может распаковать произвольные структуры данных, такие как комплексные числа (пары с плавающей запятой), записи хеш-таблицы (пары ключ-значение) и данные вершин.
Обе эти проблемы в совокупности делают невозможным реализацию эффективной общей хеш-таблицы в Java. В частности, .NET решила обе эти проблемы. Например, Общая хеш-таблица Java может быть в 17 раз медленнее, чем .NET Dictionary.
Кроме того, JVM имеют очень медленные FFI по сравнению с C++. Я слышал, что простой вызов внешней функции C из Java может занять 1000 циклов.
Обобщения, основанные на стирании типа может, в некоторых случаях работают быстрее, так как они позволяют избежать накладных расходов, связанных с созданием нескольких специализированных классов (что означает меньшее общее потребление памяти и давление кэша команд). Согласитесь, что реифицированные дженерики, вероятно, будут в среднем быстрее.
@mikera: По сравнению с C++, да. Вот почему .NET специализируется только на типах значений и сохраняет общий код над общими ссылочными типами во время выполнения. Это обеспечивает хороший компромисс с несколькими специализированными классами и без накладных расходов, когда это действительно важно (не ссылочные значения).
Все, что вы говорите о продуктивности, на самом деле зависит от вашего мнения.