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

Java Runtime Performance Vs Native C/С++ Code?

Я стал все более и более удобным программированием на Java, чем с С++ или C. Я надеюсь получить представление о производительности, вызванной использованием интерпретатора JVM, в отличие от выполнения одного и того же "проекта" изначально. Я понимаю, что здесь есть определенный уровень субъективности; качество программы будет в значительной степени зависеть от хорошей реализации. Меня интересуют следующие аспекты в общем смысле:

  • При использовании интерпретатора должна быть базовая линия для накладных расходов. Есть ли общее правило для запоминания? 10% 15%? (Я вытащил эти цифры из воздуха). Я читал случайный блог о том, что Java-код почти так же быстро, как и собственный код, но я думаю, что это может быть предвзято.

  • Собирает ли сборщик мусора JVM значительные накладные расходы для производительности во время выполнения? Я знаю, что приложения Cocoa начали использовать модель сбора мусора, и я согласен с тем, что это упрощает программирование, но по какой цене?

  • Каковы накладные расходы на выполнение системных вызовов с Java? Например, создание объекта Socket в отличие от API-интерфейса сокета.

  • Наконец, я помню, где-то читал, что реализация JVM является однопоточной. Если это правда (что я скептически отношусь), означает ли это, что потоки Java действительно не являются настоящими потоками? Является ли поток java в общем случае базовым потоком, предоставленным ядрами? Применяется ли Java-приложение так же, как собственное приложение будет работать с несколькими ядрами/несколькими процессорами?

Любые советы разработчика, которые понимают тонкости JVM и производительности Java-программы, будут высоко оценены. Спасибо.

4b9b3361

Ответ 1

Java не является интерпретированным языком и не для нескольких версий. Байт-код Java JIT'ed "на лету". (Технически он по-прежнему интерпретирует некоторые из кода, но все, что имеет значение с точки зрения производительности, получает JIT'ed)

Что касается производительности, что на Земле дает вам сумасшедшую идею о том, что "есть базовый уровень для накладных расходов"? Нет. Никогда не было и никогда не будет. Не между С++ и Java, а не между Python и Javascript или любыми другими двумя языками. Есть вещи, которые ваша конкретная версия JVM будет делать быстрее, чем ваш конкретный компилятор С++, и то, что ваш конкретный компилятор С++ будет лучше, чем ваш конкретный JVM.

Таким образом, "накладные расходы" на ваш выбор языка полностью зависят от 1) того, что вы хотите, чтобы ваш код делал, и 2) как вы пишете свой код.

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

Если вы берете программу на С++ и переводите ее на Java, это тоже будет работать медленнее.

Не потому, что один язык "быстрее", чем другой, но потому, что оригинальная программа была написана для одного языка и была приспособлена для работы на этом языке. И любая попытка перевести его на другой язык потеряет это преимущество. В итоге вы получаете Java-программу на языке С++, которая не будет эффективно работать на JVM или в Java-стиле на С++-программе, которая также будет работать ужасно.

Ни одна спецификация языка содержит предложение, что "и результат должен быть как минимум на x% медленнее, чем язык y". Как ваш компилятор С++, так и JVM делают все возможное, чтобы все ускорилось.

И тогда характеристики производительности, которые вы видите сегодня, могут измениться завтра. Языки не имеют скорости.

Но чтобы ответить на ваши конкретные вопросы:

При использовании интерпретатора должна быть базовая линия для накладных расходов. Есть ли общее правило для запоминания? 10% 15%? Я читал случайный блог о том, что Java-код почти так же быстро, как и собственный код, но я, возможно, был предвзятым.

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

Собирает ли сборщик мусора JVM значительные накладные расходы для производительности во время выполнения? Я знаю, что приложения Cocoa начали использовать модель сбора мусора, и я согласен с тем, что она упрощает программирование, но по какой цене?

В принципе нет. В среднем сборщик мусора намного быстрее, чем ручное управление памятью, по многим причинам:

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

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

(Дополнительная проблема заключается в том, что вы теряете немного выразительности. В С++ RAII используется для управления всеми видами ресурсов. В Java вы не можете использовать RAII. Вместо этого GC обрабатывает память для вас и для всех другие ресурсы, вы ввернуты и должны сделать это сами с большим количеством блоков try/finally. Нет причин, по которым RAII не может быть реализован на языке GC'ed, но он недоступен ни на Java, ни на С#),

Каковы накладные расходы на выполнение системных вызовов с Java? Например, создание объекта Socket в отличие от API сокета C.

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

Наконец, я помню, где-то читал, что реализация JVM является однопоточной. Если это правда (что я скептически отношусь), означает ли это, что потоки Java действительно не являются настоящими потоками? Является ли поток java в общем случае базовым потоком, предоставленным ядрами? Является ли приложение Java преимуществом так же, как родное приложение будет использоваться из нескольких ядер/нескольких процессоров?

Java может использовать несколько потоков, да. Сам JVM может быть однопоточным (в том смысле, что все службы JVM работают в одном потоке), я об этом не знаю. Но ваше приложение Java может использовать столько потоков, сколько им нравится, и они сопоставляются с потоками ОС и будут использовать несколько ядер.

Ответ 2

Обратитесь здесь, чтобы получить подробное сравнение.

Ответ 3

Оба java и С# (и objective-c) не так быстро, как может быть собственный код. Но это имеет значение только в том случае, если у вас есть проблема, когда вы не ограничены инженерным временем. Потому что у вас будет время для разработки лучшего алгоритма с языком высокого уровня.

В принципе, если вы разрабатываете устройство, в котором вы собираетесь построить миллион в год, или это аккумулятор, вы не используете java или С# для создания своей основной функциональности. Однако вы можете добавить интерпретатор lisp, чтобы упростить настройку. Microsoft не собирается использовать С# для ядра SQL-сервера, где производительность действительно имеет значение. Visual Studio, с другой стороны, где MS может ожидать, что пользователи будут иметь высококачественное оборудование, могут быть использованы в качестве витрины для медленных, но высокопроизводительных технологий.

Обратите внимание, что в настоящее время я занимаюсь большей частью своего программирования на Pharo Smalltalk, который намного медленнее, чем java, С# или objective-c, и даже не является одним из самых быстрых Smalltalk. Производительность козырей производительности.

Ответ 4

Многие люди недооценивают производительность Java. Мне тоже было интересно об этом, и я написал простую программу в java, а затем эквивалент в c (не намного больше, чем выполнение некоторой операции с циклом for и массивным массивом). Я не помню точных цифр, но я знаю, что java выбил c, когда c-программа не была скомпилирована с любыми флагами оптимизации (под gcc). Как и ожидалось, c вытащил вперед, когда я, наконец, скомпилировал его с агрессивной оптимизацией. Честно говоря, это был не научный эксперимент каким-либо образом, но он дал мне базовый уровень знания того, где стояла Java.

Конечно, java, вероятно, отстает, когда вы начинаете делать то, что требует системных вызовов. Хотя, я видел 100MB/s производительность чтения с дисками и сеть с java-программами, работающими на скромном оборудовании. Не уверен, что это говорит точно, но это показывает мне, что это достаточно хорошо для всего, что мне понадобится для этого.

Что касается потоков, если ваша Java-программа создает 2 потока, тогда у вас есть 2 реальных потока.

Ответ 5

http://www.w3sys.com/pages.meta/benchmarks.html

http://www.freewebs.com/godaves/javabench_revisited/

http://en.wikipedia.org/wiki/Comparison_of_Java_and_C%2B%2B#Performance

http://blog.dhananjaynene.com/2008/07/performance-comparison-c-java-python-ruby-jython-jruby-groovy/

http://www.irrlicht3d.org/pivot/entry.php?id=446

И так далее. Дело в том, что это не имеет значения. Узкие места и медленное программное обеспечение создаются разработчиками, а не языком (по крайней мере в наши дни).

Ответ 6

На самом деле, VM может делать много оптимизаций во время выполнения на основе информации, доступной только во время выполнения, которую компилятор C/С++ не может сделать. Таким образом, в большинстве случаев JVM будет, по крайней мере, так же быстро, как и родная программа.

Брайан Гетц отвечает на большинство, если не все ваши вопросы в его разговоре К универсальной виртуальной машине.

Ответ 7

Чтобы адресовать каждую из своих точек:

  • Накладные расходы интерпретирующего кода намного выше, чем 10-15% (я бы предположил, что это будет 3x-5x или выше). Чтобы перейти на 10-15%, вам нужно использовать какой-то этап компиляции машинного кода (т.е. JIT). (Попробуйте запустить JVM с выключенным JIT, и вы увидите падение производительности, как камень).
  • Сбор мусора оказывает влияние на производительность, но я бы сказал, что все согласны с тем, что это того стоит. Если вы можете позволить себе накладные расходы на компиляцию/интерпретацию байт-кода, вы также можете позволить себе накладные расходы gc.
  • Программирование сокетов намного проще на Java, чем на C/С++, если это то, что вы просите. И производительность, накладные расходы ввода-вывода сокета доминируют над служебными данными выполнения Java.
  • Большинство современных JVM имеют настоящие потоки, т.е. каждый поток Java выполняется потоком ядра, позволяя потокам Java использовать современные многоядерные процессоры.

Ответ 8

Важно отметить, что

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

против

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

Ответ 9

Ответ на этот вопрос нелегко. Написание C-стиля С++ возможно (даже хорошая идея), но как только вы пытаетесь сделать наследование на C, все становится некрасиво. Поэтому игнорируйте C и переходите с Java -vs-С++, поскольку они ближе друг к другу.

Чтобы получить реальное представление об этом, вам нужно будет написать два относительно больших приложения аналогичным образом на обоих языках. Если вы это сделаете, вы используете классы STL и Java collection, или вы пишете свои собственные и переносите их между языками? Если вы используете собственный, тогда зависит от того, какая реализация выполняется быстрее, как если бы вы использовали свою собственную, вы не проверяете реальную скорость приложения.

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

Современная реализация GC не добавляет столько накладных расходов, и вы можете переключиться на GC на С++, чтобы выполнить сравнение, если вы как: -)

Есть некоторые вещи, которые может выполнять среда выполнения Java, как правило, не выполняется в компиляторах на С++, таких как возможность встроенных виртуальных методов.

Для системного типа вещи обычно используют Java для совершения вызовов на C, поэтому там накладные расходы (хотя JNI быстрее, чем раньше).

Threading зависит от реализации. Sun использовал для использования "зеленые потоки", для Solaris, но это уже давно. Насколько я знаю большинство (все?), Современные виртуальные машины используют собственные потоки.

Короче говоря, я не думаю, что есть хорошая метрика в% накладных расходов для Java -vs-С++, и все, что вы найдете, вероятно, будут микро-ориентирами, которые не представляют реальный мир (к сожалению).

Ответ 10

Поскольку ваша цель очень скромна: "Я надеюсь получить представление о производительности...", вы должны уметь выполнять большую часть этого, изучая программы и измерения, показанные в Компьютерные игры Benchmarks Game.

Как вы знаете, как Java и С++

Но вам нужно думать о могут ли измерения крошечных программ достоверно указывать на вероятную производительность вашего приложения.