Кто-нибудь может количественно оценить различия в производительности между C ++ и Java? - PullRequest
16 голосов
/ 24 ноября 2008

До JIT Java была изначально медленной, но сегодня производительность довольно близка к C ++. Я хочу знать, проводил ли кто-нибудь измеримое сравнение производительности между двумя языками? Где Java не дотягивает по сравнению с C ++? Java обеспечивает разработчикам большую прибавку в производительности, поэтому они могут писать приложения гораздо быстрее из-за мусорного колледжа, отсутствия указателей и т. Д. Такие приложения, как Firefox, Webkit и Open Office Например, его можно было бы разработать намного быстрее и надежнее, если бы он был написан на 100% Java, возможно, в 2 раза, но разработчики по-прежнему выбирают C / C ++ по соображениям производительности. Может кто-нибудь продемонстрировать, где Java не может работать так же хорошо, как C ++ для приложений, подобных тем, которые я упомянул.

Позвольте мне просто добавить, что большая часть работы с приложениями все еще выполняется на C ++ по определенной причине. Это должно быть больше, чем субъективные вопросы. Языки с более высоким уровнем абстракции часто платят за производительность. Мы бы все программировали на языках более высокого уровня, если бы этого наказания не существовало. Где еще Java платит по сравнению с C ++? Будьте конкретны.

Ответы [ 13 ]

34 голосов
/ 24 ноября 2008

Языки не имеют скорости. Ни в спецификациях языка Java, ни в C ++ не указано, что «программы должны быть скомпилированы так, чтобы они были this эффективными».

Каждый язык определяет список того, что программа должна делать, или, по крайней мере, , кажется, делает , что в некоторых случаях ставит верхнюю границу того, насколько эффективна может быть программа, но часто - умна компилятор может игнорировать эти правила в отдельных программах, потому что все, что имеет значение, это то, что программа ведет себя , как если бы спецификация была соблюдена. Функции могут быть встроенными, данные кучи могут быть перемещены в стек и т. Д.

Производительность программы зависит от трех факторов: компилятора, базовой платформы / оборудования и самого программного кода.

Не "язык". Самый близкий к вам компилятор.

Есть веские причины, по которым один из языков может быть быстрее другого. C ++ дает меньше обещаний, которые потенциально могут замедлить выполнение программы, но Java поддерживает JIT, что означает, что он может потенциально использовать преимущества информации времени выполнения для оптимизации кода, что C ++ не может легко сделать ... И опять же, нигде в в спецификации сказано, что C ++ должен , а не быть jit'ом. Как я полагаю, есть и компиляторы Java, которые генерируют собственный код вместо байт-кода JVM.

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

Сборка мусора - еще один замечательный пример. Конечно, сборка мусора подразумевает некоторые накладные расходы, но она также допускает некоторые существенные сокращения. Выделение кучи смехотворно дешево в управляемых языках, таких как Java или .NET, , потому что управляется и собирает мусор. В C ++ это .... не определено, конечно, но на практике, как правило, очень медленно, потому что ОС приходится обходить кучу, чтобы найти свободный блок памяти в более или менее фрагментированном пространстве памяти. Какой самый быстрый? Зависит от ОС. Зависит от компилятора. Зависит от исходного кода.

Исходный код также имеет большое значение. Если вы возьмете программу Java и наивно перенесете ее на C ++, она будет работать как дерьмо. C ++ не очень хорошо справляется с виртуальными функциями, и, как правило, он предлагает превосходные альтернативы, которые вы можете использовать вместо этого. Выделение кучи может быть очень медленным в C ++, поэтому повторное выполнение Java-программы наивно будет крайне неэффективным. То же самое относится и к обратному пути. Многие идиомы C ++ были бы излишне медленными, если бы были перенесены непосредственно на Java. Так что, даже если вы остановились на одной платформе и одном компиляторе, как вы сравниваете производительность вашей программы? Чтобы даже передать его компилятору, вам нужно написать две его реализации, и тогда это уже не та же программа.

Однако, я думаю, будет справедливо сказать, что на большинстве современных аппаратных средств с современным Java-компилятором и современным C ++ -компилятором большинство программ могут быть реализованы, чтобы быть очень эффективными и, конечно, достаточно быстрыми. Но только если вы понимаете язык, с которым работаете, и играете по его правилам. Если вы попытаетесь написать код Java на C ++, то волшебным образом Java окажется гораздо более эффективным, и наоборот.

Полагаю, самый краткий ответ на ваш вопрос "Нет. Никто не может количественно оценить различия в производительности между C ++ и Java";)

16 голосов
/ 24 ноября 2008

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

Например, VonC в своем ответе на этот вопрос упоминает распределение кучи для всех объектов. На самом деле это не так: JIT может размещать объекты в стеке, если с помощью escape-анализа он может доказать, что ссылки на объект не переживут кадр стека. Таким образом, компилятор может получить выигрыш в производительности при распределении стека, а программист может быть уверен в безопасности предполагаемого выделения кучи GC.

Аналогичным образом, Ури упоминает виртуальные функции (называемые виртуальными методами в большинстве языков, отличных от C ++). Это еще один случай, когда JIT-компиляторы имеют преимущество, которое почти никогда не доступно досрочно (AOT) -компиляторам: JIT может вставить встроенную проверку дешевого типа (сравнение разыменованных слов) и фактически встроить вызов виртуального метода, если этот конкретный сайт вызова оказывается мономорфным (т.е. фактический тип на практике всегда один и тот же). Оказывается, что до 95% всех вызовов виртуальных методов на практике являются мономорфными, поэтому это может быть довольно большой выигрыш - и это выигрыш, который трудно использовать компиляторам AOT, так как во время выполнения загрузка кода может динамически изменять характеристики времени выполнения.

12 голосов
/ 24 ноября 2008

Чтобы завершить ответ Пакс и Ури, вот несколько недавних тестов:

Как уже говорилось, это два совершенно разных языка, и некоторые убеждены, что Java когда-либо будет работать медленнее, чем C ++ из-за:

  • Распределение кучи для всех объектов (даже небольших, таких как итераторы)
  • много динамических отливок
  • увеличено использование памяти

[Юмор]

«Java - это высокая производительность. Под высокой производительностью мы подразумеваем адекватную. Под адекватной мы подразумеваем медленную». г. Зайка

Как отмечается в комментариях dribeas , распределение кучи не является хорошим аргументом.
Это " Городские легенды производительности, пересмотренные " упоминает:

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

9 голосов
/ 24 ноября 2008

Еще одна скамейка: Перестрелка

7 голосов
/ 24 ноября 2008

Многие забывают, что методы JIT могут применяться к любым двоичным файлам, даже к тем, которые создаются компилятором C ++. Большинство преимуществ JIT-компиляции для Java также применимы для C ++, если вы используете что-то вроде HP Dynamo (эмулятор, который запускает исполняемые файлы быстрее, чем собственный чип и эмулирует). Профилирование во время выполнения - это не преимущество производительности Java, а компиляция JIT в целом.

7 голосов
/ 24 ноября 2008

Во многом это похоже на сравнение яблок с апельсинами.

C ++ основан на том, что вы не платите за то, что не используете. Если вы сами управляете памятью, не используете виртуальные функции и т. Д.

Ява не дает вам этой свободы. Это дает вам функции, которые вы можете даже не хотеть. Для всего, что вам захочется выделить память самостоятельно, вам придется использовать кучу объектов для всего, поэтому вы окажете влияние на сборку мусора.

Как только вы начнете говорить о графических интерфейсах, это будет еще более сложное сравнение, поскольку разные инфраструктуры и инструментарий пользовательского интерфейса имеют разные проблемы с производительностью. Например, Swing / AWT обычно работает медленнее, чем то, что написано непосредственно для родной ОС. В C ++ вы редко найдете действительно портативный инструментарий и т. Д.

Я думаю, что когда разработчики начали openoffice, Java была намного медленнее, а наборы инструментов для пользовательского интерфейса были медленными и безобразными. Такие инструменты, как Eclipse, доказывают, что вы можете создавать относительно приятные пользовательские интерфейсы даже в Java, хотя по общему признанию SWT - это набор инструментов, который делает много вещей на родном уровне.

6 голосов
/ 24 ноября 2008

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

Первые вопросы, которые нужно задать, это

  1. Что замедляет мою программу?
  2. Для моей новой программы, каковы основные соображения по проектированию производительности?

Вот несколько хороших вопросов «почему»

  • Не слишком ли много ненужных операций ввода-вывода?
  • Не слишком ли много памяти используется?
  • Является ли распределитель памяти сбитым (слишком много выделяется, слишком много мелкозернистых объектов)
  • Моя программа заблокирована на сетевой ввод-вывод на длительные периоды
  • Есть замки в неправильном месте

Я подозреваю, что вам действительно нужно сосредоточиться на аспектах P вашей программы (с большой буквой 'P) вместо p ошибок (маленький' p ') аспекты в первую очередь. Если вы можете добраться до точки, где язык находится на пути, то вы проделали действительно хорошую работу в этом направлении в отношении производительности.

Для нового кода - важно заранее планировать производительность и эффективность. Я всегда рекомендую, чтобы производительность и эффективность рассматривались так же, как и любая другая функция (они являются функциями): точно так же, как интерфейс пользователя или надежность. Конечно это будет зависеть от многих вещей, но когда это важно, вам нужно спланировать это заранее:

  • Выбор структур данных и алгоритмов, подходящих для набора данных и ожидаемого масштабирования
  • Многопоточные приложения на основе пользовательского интерфейса, где это необходимо (поток пользовательского интерфейса, фон / поток обработки)
  • План для длительных задержек ввода / вывода в сети
  • Планирование для постановки целей и измерения производительности заранее - регулярно проводите регрессивные тесты
  • Измерьте использование памяти - медленные захваты памяти (пусть начнутся японцы :))
  • Не опрашивать, когда есть события, обратные вызовы или другие механизмы уведомления

Причина, по которой я думаю, что это красная сельдь, заключается в том, что редко можно просто выбирать между C ++ и Java - это очень, очень разные языки с очень разным временем выполнения. Я подозреваю, что более обычным является то, что у вас есть другие ограничения, подталкивающие вас так или иначе - это будут факторы более высокого порядка, чем производительность языка. Совместимость с существующим кодом, навыки и опыт бывшего персонала и т. Д. И т. Д.

Окружающая среда тоже имеет значение. Например, Java почти никогда не будет правильным выбором для клиентского (в отличие от веб) приложения вдовы. И наоборот, нативный C ++ почти никогда не будет выбором для веб-приложения. (обратите внимание, я парень из Windows - ситуация может быть очень нестабильной в * nix).

5 голосов
/ 23 июня 2009

Я реализовал чувствительные к производительности приложения (физическое моделирование, финансовые модели) как на C, так и на Java. Реальность такова, что я всегда получаю гораздо больший прирост производительности, меняя алгоритмы, чем настраивая реализацию, но реализация также имеет значение. На данный момент, я считаю, что Java медленнее, чем C (у меня нет особого опыта работы с числами в C ++), но многое можно получить благодаря тщательной настройке, и эта настройка намного проще в Java, так как вы не нужно иметь дело с ошибками сегментации, двойными освобождениями и т. д. Здесь C ++ занимает промежуточное положение, поскольку современные методы C ++ (умные указатели, шаблоны, контейнеры STL) обеспечивают как скорость, так и относительную безопасность использования.

5 голосов
/ 24 ноября 2008

Некоторые моменты, которые необходимо учитывать:

  • Если вы получите лучший компилятор C ++, ваш код не станет быстрее. Вы должны сначала перекомпилировать его. Если вы получите лучшую JVM, весь ваш Java-код будет работать быстрее

  • Если вы получите лучший компилятор / JVM для C ++, вы увидите, что выполнение будет на 10-20% быстрее, обычно в угловых случаях. Если вы найдете лучший алгоритм для достижения того, что вам нужно, вы можете легко увеличить производительность на 1000–10 000%, иногда даже больше.

Итак, сегодня, если производительность является проблемой, вы должны взглянуть на эти два факта:

  • Насколько легко язык позволяет заменить один алгоритм другим? (a.k.a «Рефакторинг»)
  • Как быстро вы можете написать в нем код?

Все остальное - просто ФУД.

5 голосов
/ 24 ноября 2008

Я не верю, что кто-либо может доказать, что C ++ всегда будет значительно быстрее, чем Java, просто потому, что вы всегда можете вернуться к JNI, чтобы получить естественную скорость от Java.

См., Например, SWT, графический инструмент, созданный IBM (я думаю), предназначенный для замены Swing и обеспечения как собственной производительности, так и внешнего вида.

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

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