Может ли Java быть быстрее C ++ в любой ситуации? - PullRequest
0 голосов
/ 02 января 2009

Возможно ли, чтобы приложение Java было быстрее, чем программа, написанная на C ++? Кроме того, что такое режим релиза при компиляции?

Ответы [ 10 ]

19 голосов
/ 06 января 2009

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

Да, типичная реализация Java может быть быстрее, чем типичная реализация C ++ для реальных вещей. Несмотря на то, что у Java есть некоторые недостатки из-за того, что она является безопасным языком виртуальных машин, она также компенсирует некоторые из них.

С одной стороны, поскольку Java имеет очень абстрактную схему управления памятью, которая не позволяет манипулировать необработанными указателями или нетипизированными блоками памяти, она может использовать движущийся сборщик мусора. В C ++ нетипизированные области памяти, объединения и т. Д. Сломали бы это. Поэтому, когда GC не нужно запускать, выделения в Java могут быть просто ударом указателя. В C ++ нет практического способа сделать это, поскольку полностью движущийся GC не может быть реализован на языке, который поддерживает тот тип низкоуровневых манипуляций, который делает C ++.

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

abstract class Foo {
    void stuff() {}
}

class Foo1 extends Foo {
    void stuff()  {
        System.out.println("Foo1");
    }
}

class Foo2 extends Foo {
    void stuff()  {
        System.out.println("Foo2");
    }
}

// Somewhere in program initialization:
Foo foo;
if(args[0] == "Foo1")
    foo = new Foo1();
 else foo = new Foo2;
 for(int i = 0; i < 1000000; i++)
     foo.stuff();

В C ++ вызов виртуальной функции для foo.stuff (), вероятно, должен выполняться для всех 1 000 000 итераций. В Java виртуальная машина могла бы заменить это прямым вызовом во время выполнения, поняв, что не существует семантически законного способа откатить foo к объекту класса Foo2.

13 голосов
/ 02 января 2009

Языки не имеют скорости. Хороший компилятор Java может генерировать более эффективный код, чем плохой компилятор C ++, и наоборот. Так какой из них "самый быстрый"?

Скорость исполнения зависит от нескольких факторов:

  • Компилятор. Разные компиляторы генерируют разные выходные коды из одного и того же ввода.
  • Ваш исходный код. Некоторые операции дешевы на одном языке, но дороги на других. выделение памяти с помощью 'new' намного медленнее в C ++, чем в управляемом языке, таком как C # или Java, например)
  • Система, на которой работает. (Процессоры различаются по тому, насколько быстро они могут выполнять другой код. Что если ваш компилятор Java сгенерирует код, который действительно хорошо работает на Core 2, но мой компилятор C ++ генерирует код, который хорошо работает на Phenom? 1010 *

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

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

Скажите после меня: Языки не имеют скорости .

Какой самый быстрый? Английский или французский? Оба - просто способы связать значение со звуками или загогулины на бумаге.

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

7 голосов
/ 02 января 2009

Я думаю, что вы можете просмотреть множество вопросов, которые похожи. Посмотрите здесь, например: Производительность C ++ против Java / C #

2 голосов
/ 02 января 2009

Да, он может: создать программу на Java, которая использует хороший алгоритм, и программу на C ++, которая использует плохой алгоритм, и версия Java, вероятно, будет быстрее.

1 голос
/ 07 октября 2009

Вы можете увидеть c ++ и язык Java сравнение , где в нескольких случаях Java работает быстрее. Также я добавил таблицы для Java и C ++, и вы можете видеть, что некоторые другие случаи быстрее в Java по сравнению с C ++.

Чем ниже цифры, тем лучше. Например, поиск двоичных деревьев лучше в java (2.89) с против 4.47 с в c ++.

http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=javaxx&lang2=javaxx
<code>
 Java 6 -Xms64m measurements
Program & Logs  Time secs   Memory KB   Size B   N 
binary-trees    2.89    39,436  603  16
chameneos-redux 17.01   17,316  1429     6,000,000
fannkuch    11.08   8,996   555  11
fasta   21.40   9,300   1240     25,000,000
k-nucleotide    15.57   83,308  1052     1,000,000
mandelbrot  3.25    11,136  665  3,000
meteor-contest  0.80    14,196  5177     2,098
n-body  14.84   11,652  1424     20,000,000
nsieve  2.22    15,748  296  9
nsieve-bits 5.04    13,468  523  11
partial-sums    9.14    8,600   474  2,500,000
pidigits    1.92    9,112   938  2,500
recursive   6.82    12,180  427  11
regex-dna   7.60    75,192  921  500,000
reverse-complement  1.13    61,124  592  2,500,000
spectral-norm   24.00   12,268  514  5,500
startup 17.23       112  200
sum-file    4.11    10,084  226  21,000
thread-ring 134.99  27,628  530  10,000,000
</code>
http://shootout.alioth.debian.org/gp4/benchmark.php?test=all&lang=gpp&lang2=gpp
<code>
 C++ GNU g++ measurements
Program & Logs  Time secs   Memory KB   Size B   N 
binary-trees    4.47    6,996   541  16
chameneos-redux 16.69   1,004   1729     6,000,000
fannkuch    7.78    844 554  11
fasta   18.72   788 1248     25,000,000
k-nucleotide    7.46    9,304   1380     1,000,000
mandelbrot  3.02    896 1097     3,000
meteor-contest  0.15    792 5311     2,098
n-body  14.62   932 1705     20,000,000
nsieve  2.08    5,764   313  9
nsieve-bits 3.86    3,316   494  11
partial-sums    4.05    852 531  2,500,000
pidigits    1.66    1,052   652  2,500
recursive   2.40    1,008   566  11
regex-dna   5.58    12,704  1588     500,000
reverse-complement  0.54    13,288  810  2,500,000
spectral-norm   23.84   900 442  5,500
startup 0.86        108  200
sum-file    6.47    852 260  21,000
thread-ring 101.28  2,960   626  10,000,000
</code>
0 голосов
/ 18 декабря 2009

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

OTOH, это ничего не присуще рассматриваемым языкам. Пару лет назад я видел исследовательский проект, в котором удалось получить дополнительные 20% от некоторого встроенного кода (возможно, даже из C ++), запустив его в эмуляторе, имитирующем тот же процессор, что и оборудование, но выполнив некоторые оптимизации в стиле VM по коду.

0 голосов
/ 07 октября 2009

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

0 голосов
/ 07 января 2009

Режим выпуска означает, что вы создаете свою программу, потому что вы хотите опубликовать ее для общественности. Обычно компилятор старается сделать исполняемый файл меньше и быстрее. Это часто означает, что необходимо избавиться от информации о символах, необходимой для восстановления после сбоя, и использовать более высокий уровень оптимизации. Последнее замедляет время компиляции, поэтому оно не используется при сборке в Режим отладки .

0 голосов
/ 02 января 2009

Если я верю тому, что говорят некоторые евангелисты Java, я бы ответил «да» на первый вопрос. То есть. Java-программа «может» быть быстрее. Хотя не всегда ...
Эти евангелисты Java указывают на лучшее управление памятью, избегая затрат на new и т. Д.

Чтобы ответить на второй вопрос, режим выпуска для компилятора C / C ++ означает компиляцию без отладочной информации: последний хранит дополнительную информацию, такую ​​как номера строк, соответствующие сгенерированному коду (проще для отладки и создания отчетов об ошибках), и избегает оптимизаций (которые может изменить порядок кода и связываться с вышеуказанной информацией).
Так что режим релиза, как правило, быстрее и меньше. И может произойти сбой, когда работает режим отладки! (Редко, но я видел это.)

0 голосов
/ 02 января 2009

Да, это может . JIT-компилятор может оптимизировать код для более быстрой работы. В то время как в C ++ вы должны сделать это вручную.

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