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

Сборники Java быстрее, чем контейнеры С++?

Я читал комментарии к этому ответу, и я увидел эту цитату.

Объектно-ориентированные функции и объектно-ориентированные функции быстро используются (быстрее, чем С++ во многих случаях), потому что они разработаны с самого начала. и Коллекции бывают быстрыми. Стандартная Java превосходит стандартную C/С++ в этой области, даже для большинства оптимизированных C-кодов.

Один пользователь (с действительно высоким rep, который я мог бы добавить) смело защищал это утверждение, заявляя, что

  • выделение кучи в java лучше, чем С++

  • и добавил этот оператор, защищающий коллекции в java

    И коллекции Java быстро сравниваются с коллекциями С++, в основном из-за разной подсистемы памяти.

Итак, мой вопрос: может ли это быть действительно так, и если да, то почему распределение java-кучи намного быстрее.

4b9b3361

Ответ 1

Такое утверждение нелепо; люди делают это либо невероятно неосведомленным, либо невероятно нечестным. В в частности:

  • Скорость распределения динамической памяти в двух случаях будет зависят от модели использования динамической памяти, а также от реализация. Для кого-то, знакомого с алгоритмы, используемые в обоих случаях, чтобы написать контрольный тест, который когда-либо он хотел быть быстрее. (Таким образом, например, программы используя большие сложные графики, которые строятся, затем срываются и перестроен, обычно будет работать быстрее при сборке мусора. В виде будут программы, которые никогда не будут использовать достаточную динамическую память для запуска коллектор. Программы, использующие несколько, больших, долгоживущих распределения будут выполняться быстрее с ручной памятью управление.)

  • При сравнении коллекций вы должны учитывать, что такое в коллекциях. Если вы сравниваете большие векторы double, например, разница между Java и С++ будет вероятно, будет незначительным и может идти в любом случае. Если вы сравниваете большие векторы Point, где Point - класс значений, содержащий два двухлокальных, С++, вероятно, выведет Java из воды, потому что он использует семантику чистого значения (без дополнительной динамической распределение), где, когда Java должна динамически распределять каждый Point (и динамическое распределение не всегда быстрее, чем четное самое быстрое динамическое распределение). Если класс Point в Java правильно рассчитана на то, чтобы действовать как ценность (и, следовательно, неизменная, например, java.lang.String), а затем выполнить перевод на Point в векторе потребуется новое распределение для каждого Point; в С++, вы можете просто назначить.

  • Многое зависит от оптимизатора. В Java оптимизатор работает с полным пониманием фактических вариантов использования, в этом конкретный запуск программы и совершенное знание фактический процессор, на котором он запущен, в этом запуске. В С++ оптимизатор должен работать с данными из профилирующего прогона, который будет никогда не соответствуют точно одному прогоню программы, и Оптимизатор должен (обычно) генерировать код, который будет запускаться (и запускаться быстро) на самых разных версиях процессора. С другой стороны, оптимизатор С++ может занять значительно больше времени анализируя разные пути (и эффективная оптимизация может требуется много CPU); оптимизатор Java должен быть справедливым быстро.

  • Наконец, хотя это не относится ко всем приложениям, С++ может быть однопоточный. В этом случае блокировка не требуется в распределитель, который никогда не имеет места в Java.

Что касается двух пронумерованных точек: С++ может использовать больше или меньше тех же алгоритмов, что и Java в распределителе кучи. Я использовали программы на С++, где функция ::operator delete() была пустой, и память была собрана мусором. (Если ваш приложение выделяет много короткоживущих, мелких объектов, таких как распределитель, вероятно, ускорит работу.) А что касается во-вторых: действительно большое преимущество С++ заключается в том, что его память модель не требует, чтобы все было динамически распределено. Даже если выделение на Java занимает всего лишь десятую часть времени будет принимать на С++ (что может быть, если вы только считаете распределение, а не время, необходимое для коллекционера sweeps), с большими векторами Point, как указано выше, вы сравнивая два или три распределения в С++ с миллионами распределения в Java.

И, наконец, "почему распределение кучи Java намного быстрее?" Это не обязательно, если вы амортизируете время для фаз сбора. Время для самого распределения может быть очень дешево, потому что Java (или, по крайней мере, большинство реализаций Java) используйте перемещающий коллектор, в результате чего все свободные память находится в одном непрерывном блоке. Это по крайней мере частично компенсируется временем, необходимым в коллекторе: получить эта смежность, вам нужно переместить данные, что означает много копирование. В большинстве реализаций это также означает косвенность в указателях и много специальной логики, чтобы избежать когда один поток имеет адрес в регистре или такой.

Ответ 2

В ваших вопросах нет конкретных ответов. Например, С++ вообще не определяет управление памятью. Он оставляет детали распределения до реализации библиотеки. Поэтому в пределах С++ у данной платформы может быть очень медленная схема распределения кучи, и Java, несомненно, будет быстрее, если она обходит это. На другой платформе распределение памяти может быстро разгоняться, превосходя Java. Как отметил Джеймс Канзе, Java также помещает очень мало ограничений в управлении памятью (например, даже алгоритм GC полностью зависит от разработчика JVM). Поскольку Java и С++ не создают ограничений на управление памятью, нет конкретного ответа на этот вопрос. С++ целенаправленно раскрывает основные функции ядра и ядра, а Java целенаправленно раскрывает информацию об управлении памятью JVM. Поэтому вопрос становится очень нечетким.

Вы можете обнаружить, что некоторые операции быстрее в Java, а некоторые нет. Вы никогда не знаете, пока не попытаетесь:

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

В общем, как только вы обнаружите, что думаете или читаете о проблемах с С++ и Java, остановите и переориентируйте на что-то продуктивное.

Ответ 3

Куча Java быстрее, потому что (упрощенное) все, что вам нужно сделать для выделения, - это увеличить указатель кучи (как и в стеке). Это возможно, потому что куча периодически уплотняется. Таким образом, ваша цена за скорость:

  • Периодические GC-паузы для уплотнения кучи
  • Увеличение использования памяти

Нет бесплатного сыра... Поэтому, когда операции по сбору данных могут быть быстрыми, они амортизируются общим замедлением во время работы GC.

Ответ 4

Пока я поклонник Java, стоит отметить, что С++ поддерживает выделение объектов в стеке быстрее, чем распределение кучи.

Если вы используете С++ эффективно со всеми его различными способами делать то же самое, это будет быстрее, чем Java (даже если вам потребуется больше времени, чтобы найти эту оптимальную комбинацию)

Если вы программируете на С++, как в Java, например. все в куче, все методы виртуальные, имеют много проверок времени выполнения, которые ничего не делают и могут быть оптимизированы динамически, это будет медленнее. Java оптимизировала эти вещи дальше, поскольку они: а) являются единственной вещью, которую делает Java, б) могут быть оптимизированы динамически более эффективно, c) у Java меньше возможностей и побочных эффектов, поэтому для оптимизатора легче получать приличные скорости.

Ответ 5

и коллекции быстро. Стандартная Java превосходит стандартную C/С++ в этой области, даже для большинства оптимизированных C-кодов.

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

Например, java.util.HashMap будет превосходить a std:map, потому что последнее необходимо сортировать. То есть самая быстрая карта в стандартной библиотеке Java быстрее, чем самая быстрая карта на С++ (по крайней мере до С++ 11, которая добавила std:unordered_map)

С другой стороны, std:Vector<int> намного эффективнее, чем java.util.ArrayList<Integer> (из-за стирания типа вы не можете использовать java.util.ArrayList<int>, и, следовательно, в итоге примерно в 4 раза больше потребления памяти и возможно, более низкая локальность кэша и, соответственно, более медленная итерация).

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