Иногда Java превосходит C ++ в тестах. Конечно, иногда C ++ выигрывает.
Смотрите следующие ссылки:
- http://keithlea.com/javabench/
- http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/
- http://blog.cfelde.com/2010/06/c-vs-java-performance/
Но как это вообще возможно? Меня поражает, что интерпретируемый байт-код может быть быстрее, чем скомпилированный язык.
Может кто-нибудь объяснить, пожалуйста? Спасибо!
java
c++
performance
Deets McGeets
источник
источник
Ответы:
Во-первых, большинство JVM включают в себя компилятор, поэтому «интерпретируемый байт-код» на самом деле довольно редко (по крайней мере, в тестовом коде - это не так уж редко в реальной жизни, когда ваш код обычно представляет собой несколько простых циклов, которые повторяются очень часто ).
Во-вторых, значительное число задействованных критериев выглядит довольно предвзятым (я не могу сказать, по намерению или по некомпетентности). Например, несколько лет назад я посмотрел на исходный код, связанный с одной из опубликованных вами ссылок. У него был такой код:
Так как
calloc
обеспечивает нулевую память, использованиеfor
цикла для обнуления снова бесполезно. За этим последовало (если память служит) заполнение памяти другими данными в любом случае (и никакой зависимости от обнуления), поэтому все обнуление было совершенно ненужным в любом случае. Замена приведенного выше кода на простоеmalloc
(как любой здравомыслящий человек использовал бы для начала) улучшило скорость версии C ++, достаточную для того, чтобы превзойти версию Java (с довольно большим запасом, если память будет работать).Рассмотрим (для другого примера)
methcall
тест, использованный в записи блога в вашей последней ссылке. Несмотря на название (и как вещи могут даже выглядеть), версия этого языка на C ++ не особо измеряет затраты на вызовы методов вообще. Часть кода, которая оказывается критической, находится в классе Toggle:Критическая часть оказывается
state = !state;
. Рассмотрим, что происходит, когда мы изменяем код для кодирования состоянияint
вместоbool
:Это незначительное изменение улучшает общую скорость примерно на 5: 1 . Несмотря на то, что эталонный тест предназначался для измерения времени вызова метода, в действительности большая часть того, что он измерял, была временем преобразования между
int
иbool
. Я, безусловно, согласен с тем, что неэффективность, показанная оригиналом, вызывает сожаление - но учитывая, как редко он возникает в реальном коде, и легкость, с которой его можно исправить, когда / если он возникает, мне трудно думать это так много значит.В случае, если кто-то решит повторно запустить соответствующие тесты, я должен также добавить, что есть почти одинаково тривиальное изменение в версии Java, которая производит (или, по крайней мере, когда-то произведено) - я не запускал тесты повторно с недавняя JVM, чтобы подтвердить, что они все еще делают) довольно существенное улучшение в версии Java также. В версии Java есть NthToggle :: activ (), который выглядит следующим образом:
Изменение этого параметра для вызова базовой функции вместо
this.state
непосредственного управления дает довольно существенное улучшение скорости (хотя этого недостаточно, чтобы не отставать от модифицированной версии C ++).Итак, в результате мы получаем ложное предположение о интерпретируемых байтовых кодах и некоторые из худших тестов (которые я когда-либо видел). Ни один не дает значимого результата.
Мой собственный опыт показывает, что при одинаково опытных программистах, уделяющих одинаковое внимание оптимизации, C ++ будет превосходить Java чаще, чем нет - но (по крайней мере, между этими двумя) язык редко будет иметь такое же большое значение, как программисты и дизайн. Упомянутые критерии говорят нам больше о (не) компетентности / (не) честности их авторов, чем о языках, на которые они ориентированы.
[Править: Как подразумевается в одном месте выше, но никогда не указывалось так явно, как мне следовало бы, результаты, которые я цитирую, - это те результаты, которые я получил, когда тестировал это ~ 5 лет назад, используя реализации C ++ и Java, которые были актуальны в то время , Я не перезапускал тесты с текущими реализациями. Однако взгляд указывает, что код не был исправлен, поэтому все, что изменилось бы, это способность компилятора скрыть проблемы в коде.]
Если мы будем игнорировать примеры Java, однако, это действительно возможно интерпретировать код , чтобы работать быстрее , чем скомпилированный код (хотя трудно и несколько необычно).
Обычный способ, которым это происходит, заключается в том, что интерпретируемый код гораздо более компактен, чем машинный код, или он работает на процессоре, который имеет больший кэш данных, чем кэш кода.
В таком случае небольшой интерпретатор (например, внутренний интерпретатор реализации Forth) может полностью уместиться в кеше кода, а программа, которую он интерпретирует, полностью умещается в кеше данных. Кэш обычно быстрее, чем основная память, как минимум в 10 раз, а зачастую и намного больше (в 100 раз больше не редкость).
Таким образом, если кэш быстрее, чем основная память, с коэффициентом N, и для реализации каждого байтового кода требуется меньше, чем N инструкций машинного кода, байт-код должен выиграть (я упрощаю, но я думаю, что общая идея должна все же быть очевидным).
источник
Свернутый вручную C / C ++, выполненный экспертом с неограниченным временем , будет, по крайней мере, таким же быстрым или быстрым, как Java. В конечном счете, сама Java написана на C / C ++, поэтому вы, конечно, можете делать все, что делает Java, если вы готовы приложить достаточно усилий для разработки.
Однако на практике Java часто выполняется очень быстро по следующим причинам:
В то же время C / C ++ также имеет некоторые преимущества:
В целом:
источник
Среда выполнения Java не интерпретирует байт-код. Скорее, он использует то, что называется сборкой Just In Time . В основном, когда программа запускается, она берет байт-код и преобразует его в собственный код, оптимизированный для конкретного процессора.
источник
При прочих равных условиях можно сказать: нет, Java никогда не должна быть быстрее . Вы всегда можете реализовать Java на C ++ с нуля и, таким образом, добиться как минимум такой же высокой производительности. На практике, однако:
Кроме того, это напоминает мне о дебатах, касающихся C в 80-х / 90-х годах. Всем было интересно, "может ли C когда-нибудь быть таким же быстрым, как сборка?" По сути, ответ был: нет на бумаге, но на самом деле компилятор C создал более эффективный код, чем 90% программистов на ассемблере (ну, когда он немного повзрослел).
источник
http://www.ibm.com/developerworks/java/library/j-jtp09275/index.html
источник
Хотя полностью оптимизированная Java-программа редко превосходит полностью оптимизированную C ++-программу, различия в таких вещах, как управление памятью, могут сделать множество алгоритмов, идиоматически реализованных в Java, быстрее, чем те же алгоритмы, идиоматически реализованные в C ++.
Как отметил @Jerry Coffin, во многих случаях простые изменения могут сделать код намного быстрее, но часто может потребоваться слишком много грязных настроек на одном языке или другом, чтобы повысить производительность. Это, вероятно, то, что вы увидите в хорошем тесте, который показывает, что Java работает лучше, чем C ++.
Кроме того, хотя обычно это не так важно, есть некоторая оптимизация производительности, которую JIT-язык, такой как Java, может сделать, чего не может C ++. Среда выполнения Java может включать улучшения после компиляции кода, что означает, что JIT потенциально может создавать оптимизированный код, чтобы использовать преимущества новых (или, по крайней мере, других) функций ЦП. По этой причине 10-летний двоичный файл Java может потенциально превзойти 10-летний двоичный файл C ++.
Наконец, полная безопасность типов в более широкой картине, в очень редких случаях, может предложить экстремальные улучшения производительности. Singularity , экспериментальная ОС, написанная почти полностью на языке C #, имеет намного более быстрое межпроцессное взаимодействие и многозадачность из-за того, что нет необходимости в аппаратных границах процессов или дорогостоящих переключениях контекста.
источник
Автор: Тим Холлоуэй на JavaRanch:
Источник: http://www.coderanch.com/t/547458/Performance/java/Ahead-Time-vs-Just-time
источник
Это связано с тем, что последний шаг генерации машинного кода происходит прозрачно внутри JVM при запуске Java-программы, а не явно при создании программы C ++.
Вам следует учитывать тот факт, что современные JVM тратят довольно много времени на компиляцию байт-кода на лету для машинного кода, чтобы сделать его максимально быстрым. Это позволяет JVM выполнять всевозможные трюки компилятора, которые могут быть еще лучше, зная данные профилирования выполняемой программы.
Просто такая вещь, как автоматическое включение геттера, так что JUMP-RETURN не нужен, чтобы просто получить значение, ускоряет процесс.
Однако, вещь, которая действительно позволила быстрые программы, лучше очищать впоследствии. Механизм сборки мусора в Java работает быстрее, чем ручной, не содержащий malloc в C. Во многих современных реализациях без malloc используется сборщик мусора.
источник
Краткий ответ - это не так. Забудьте об этом, тема так же стара, как огонь или колесо. Java или .NET не является и не будет быстрее, чем C / C ++. Это достаточно быстро для большинства задач, когда вам вообще не нужно думать об оптимизации. Как формы и обработка SQL, но на этом все и заканчивается.
Для тестов или небольших приложений, написанных некомпетентными разработчиками, да, конечным результатом будет то, что Java / .NET, вероятно, будет близко и, возможно, даже быстрее.
В действительности, простые вещи, такие как выделение памяти в стеке или просто использование memzones, просто убьют Java / .NET на месте.
Мусоросборный мир использует что-то вроде memzone со всеми учетными записями. Добавьте memzone к C, и C будет быстрее прямо на месте. Специально для тех тестов «высокопроизводительный код» Java и C, которые идут так:
Попробуйте использовать переменные на основе стека в C / C ++ (или размещение новых), они переводятся в
sub esp, 0xff
, это отдельная инструкция x86, лучше, чем в Java - вы не можете ...Большую часть времени я вижу те стенды, где сравнивают Java с C ++, это заставляет меня идти, wth? Неправильные стратегии выделения памяти, саморазвивающиеся контейнеры без резервов, множество новых. Это даже не близко к ориентированному на производительность коду C / C ++.
Также хорошо читать: https://days2011.scala-lang.org/sites/days2011/files/ws3-1-Hundt.pdf
источник
Реальность заключается в том, что они оба являются просто ассемблерами высокого уровня, которые делают именно то, что им говорит программист, точно так, как программист говорит им в точном порядке, который им говорит программист. Различия в производительности настолько малы, что несущественны для всех практических целей.
Язык не «медленный», программист написал медленную программу. Очень редко программа, написанная наилучшим образом на одном языке, превосходит (для любой практической цели) программу, выполняющую то же самое с использованием наилучшего способа на альтернативном языке, если только автор исследования не пытается размять свой конкретный топор.
Очевидно, что если вы собираетесь использовать такой редкий случай, как жесткие встроенные системы реального времени, выбор языка может иметь значение, но как часто это происходит? и из тех случаев, как часто правильный выбор не очевиден.
источник
Кит Ли говорит вам, что есть "очевидные недостатки", но ничего не делает с этими "очевидными недостатками". Еще в 2005 году эти старые задачи были отброшены и заменены задачами, которые теперь показаны в тестовой игре .
Кит Ли говорит вам, что он «взял эталонный код для C ++ и Java из устаревшей версии Great Computer Language Shootout и провел тесты», но на самом деле он показывает результаты только для 14 из 25 этих устаревших тестов .
Кит Ли теперь говорит вам, что он не пытался что-либо доказать с помощью поста в блоге семь лет назад, но тогда он сказал: «Мне надоело слышать, как люди говорят, что Java работает медленно, когда я знаю, что это довольно быстро ...», что говорит о том, что тогда было что-то, что он пытался доказать.
Кристиан Фельде говорит вам: «Я не создавал код, просто перезапустил тесты». как будто это освобождает его от какой-либо ответственности за его решение обнародовать измерения задач и программ, выбранных Китом Ли.
Измерения даже 25 крошечных крошечных программ обеспечивают окончательное доказательство?
Эти измерения предназначены для программ, работающих в «смешанном режиме» Java, а не в интерпретации Java - «Помните, как работает HotSpot». Вы можете легко узнать, насколько хорошо Java выполняет «интерпретированный байт-код», потому что вы можете заставить Java интерпретировать только байт-код - просто время, когда некоторые программы Java работают с опцией -Xint и без нее.
источник
Меня удивляет, насколько распространено это странное понятие «интерпретируемый байт-код». Вы когда-нибудь слышали о JIT-компиляции? Ваш аргумент не может быть применен к Java.
Но, оставляя JVM в стороне, бывают случаи, когда прямой многопоточный код или даже тривиальная интерпретация байт-кода могут легко превзойти сильно оптимизированный нативный код. Объяснение довольно простое: байт-код может быть достаточно компактным и соответствовать вашему крошечному кешу, когда версия того же алгоритма с собственным кодом будет иметь несколько кеш-пропусков за одну итерацию.
источник
За исключением JIT, GC и так далее, C ++ может быть очень и очень легко сделан гораздо более медленным, чем Java. Это не будет отображаться в тестах, но одно и то же приложение, написанное разработчиком Java и разработчиком C ++, может быть намного быстрее в Java.
Что касается расширенных шаблонов наследования, они в значительной степени похожи - в C ++ есть такие, которых нет в Java, и наоборот, но все они также вносят аналогичные значительные издержки. Так что нет особого преимущества C ++ в объектно-насыщенном программировании.
Еще одно предостережение: GC может быть быстрее или медленнее, чем управление распределением вручную. Если вы выделяете много небольших объектов, в среде GC обычно выделяется кусок памяти и ее части распределяются по мере необходимости для новых объектов. В управляемом - каждый объект = отдельное выделение занимает значительное время. OTOH, если вы используете malloc () много памяти одновременно, а затем просто присваиваете ее части своим объектам вручную или используете несколько больших экземпляров объектов, вы можете появиться намного быстрее.
источник
obj.fetchFromDatabase("key")
три раза в пяти строках кода для одного и того же ключа, вы дважды подумаете, следует ли извлечь это значение один раз и кэшировать его в локальной переменной. Если вы пишетеobj->"key"
с->
перегрузкой, чтобы действовать как выборка из базы данных, вы гораздо более склонны просто пропустить ее, потому что стоимость операции не очевидна.Каким-то образом Stack Exchange не берет другие мои стековые точки, так что ... нет ответа, к сожалению ...
Тем не менее, второй самый голосующий ответ здесь полон дезинформации по моему скромному мнению.
Созданное вручную специалистом по C / C ++ приложение ВСЕГДА будет намного быстрее, чем Java-приложение. Там нет «так быстро, как Java или быстрее». это просто быстрее, именно из-за пунктов, которые вы цитируете ниже:
JIT-компиляция : Вы действительно ожидаете, что автоматический оптимизатор будет обладать умением опытного программиста и увидит связь между намерением и кодом, который ЦП действительно собирается запустить ??? Кроме того, все, что вы делаете, - это потеря времени по сравнению с уже скомпилированной программой.
Сборщик мусора - это инструмент, который просто освобождает ресурсы, которые программист забыл бы освободить, более или менее эффективно.
Очевидно, это может быть только медленнее, чем то, что программист C (вы выбрали термин) сделал бы для управления своей памятью (и нет никаких утечек в правильно написанных приложениях).
Приложение C с оптимизированной производительностью знает процессор, на котором оно работает, оно скомпилировано на нем, иначе это означает, что вы не совсем предприняли все шаги для повышения производительности, не так ли?
Статистика времени выполнения Это вне моих знаний, но я подозреваю, что у эксперта в Си более чем достаточно знаний по прогнозированию веток, чтобы снова перехитрить автоматизированную оптимизацию -
Очень хорошие библиотеки. Есть много неоптимизированных функций, доступных через библиотеки на Java, и то же самое верно для любого языка, однако наиболее оптимизированные библиотеки написаны на C, особенно для вычисления.
JVM - это уровень абстракции, который подразумевает как хорошие вещи, многие из которых перечислены выше, так и подразумевает, что общее решение медленнее по своей конструкции.
В целом:
Java никогда не сможет достичь скорости C / C ++ из-за того, как она работает в JVM со множеством средств защиты, функций и инструментов.
У C ++ есть определенное явное преимущество в оптимизированном программном обеспечении, будь то для вычислений или игр, и обычные случаи, когда реализации C ++ выигрывают в соревнованиях по программированию, приводят к тому, что лучшие реализации Java можно увидеть только на второй странице.
На практике C ++ не является игрушкой и не позволит вам избежать многих ошибок, с которыми может справиться большинство современных языков, однако, будучи проще и менее безопасным, он по своей природе быстрее.
И в заключение я хотел бы сказать, что большинство людей не дают по два цента по этому поводу, что в конечном итоге оптимизация - это спорт, предназначенный только для очень немногих счастливчиков-разработчиков, и это, за исключением случаев, когда производительность действительно является проблемой (То есть умножение аппаратного обеспечения на 10 не поможет вам - или, по крайней мере, составит несколько миллионов), большинство менеджеров предпочтут неоптимизированное приложение и тонну аппаратного обеспечения.
источник
new
илиmalloc()
. В целом это может быть намного быстрее, чем любое ручное управление памятью, поскольку вы не сможете перемещать объекты вручную. Итак, все ваши рассуждения явно ошибочны и предвзяты. Ваши знания об алгоритмах GC и методах оптимизации JIT слишком ограничены.Я видел, по крайней мере, две впечатляющие mmo, сделанные на Java, и сказать, что это недостаточно быстро для игр - это неправильно. Просто потому, что разработчики игр предпочитают C ++ больше, чем другие языки, говорят, что он не просто связан с Java, это просто означает, что программисты никогда не баловались с какими-либо другими языками программирования / парадигмами. Все на любом языке, более продвинутом, как C / C ++ или даже Java, может создавать код, который может технически соответствовать или опровергать аргумент скорости. Все, что хорошо и сказано, сводится к тому, что программисты знают, с какими командами работает больше всего, и самое главное, почему они используют эти инструменты. Поскольку мы занимаемся разработкой игр в аспекте программирования, в этом должен быть аргумент. Проще говоря Все дело в деньгах и времени для делового тупика, использующего инструменты, отвечающие требованиям QA, и в реальном мире не имеет никакого значения для xx причин выбора C ++ вместо Java или любого другого языка. Это просто решение для массового производства. На самом базовом уровне вычислительных алгоритмов все, с чем мы играем, это единицы и нули, аргумент скорости - один из самых глупых аргументов, когда-либо применяемых к играм. Если вы хотите получить быстрое увеличение скорости, полностью исключите языки программирования и работайте со сборкой, что, возможно, является лучшим преимуществом на сегодняшний день.
источник