Java действительно медленная?

180

Java имеет некоторую степень репутации медлительности .

  • Java действительно медленная?
  • Если да, то почему? Где (или было) узкое место? Это из-за неэффективных JVM? Вывоз мусора? Чистые библиотеки байт-кода вместо J-кодированного C-кода? Многие другие языки имеют эти функции, но у них нет репутации медлительности.
Стефано Борини
источник
35
люди так нервничают ... не видят, как это может быть субъективным и аргументным. Интересно, если бы такой вопрос, как «почему пузырьковая сортировка идет медленно», дал бы такой же результат? Я задал технический вопрос и хотел получить технические ответы (которые я получил), но закрывать вопрос как субъективный и спорный нелепо.
Стефано Борини
1
Я прочитал большинство главных комментариев, и ни один из них, по-видимому, не отражает явный факт, что настольные приложения на основе C # GUI работают намного быстрее, чем любые настольные приложения на основе Java GUI, включая современные.
BobTurbo
3
Как веб-разработчик на стороне клиента, который имел дело с .net webforms, .net MVC, PHP, Rails, Django и множеством всего, кроме Spring (что я слышал хорошо) в Java, я ожидаю плохой производительности / архитектуры от бэк-эндов, построенных командами Java. Я подозреваю, что настоящая проблема не в эталонных тестах, а в том, что существует просто дерьмо посредственных разработчиков Java. Это не вина языка. Это не вина разработчиков Java, которые на самом деле оттачивают свое мастерство и изучают языки, отличные от Java. Однако это может быть ошибка Sun, Certs, 90-х и IT-индустрии в целом.
Эрик Реппен

Ответы:

236

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

Если вы все еще думаете, что Java работает медленно , посмотрите результаты тестов игры . Сильно оптимизированный код, написанный на заранее скомпилированном языке (C, Fortran и т. Д.), Может превзойти его; однако Java может быть более чем в 10 раз быстрее, чем PHP, Ruby, Python и т. д. Существуют определенные области, в которых он может превзойти обычные скомпилированные языки (если они используют стандартные библиотеки).

Теперь нет оправдания «медленным» Java-приложениям. Виноваты разработчики и устаревший код / ​​библиотеки, гораздо больше, чем язык. Также во всем виноват «предприятие».

Честно говоря, толпа «Java медленная», вот области, где она все еще медленная (обновлено для 2013):

  • Библиотеки часто пишутся для «правильности» и читабельности, а не производительности. На мой взгляд, это главная причина, по которой у Java все еще плохая репутация, особенно на стороне сервера. Это делает проблемы со строками экспоненциально хуже. Часто встречаются простые ошибки: объекты часто используются вместо примитивов, что снижает производительность и увеличивает использование памяти. Многие библиотеки Java (включая стандартные) часто создают строки, а не используют изменяемые или более простые форматы (char [] или StringBuffer). Это медленно и создает тонны мусора для последующего сбора. Чтобы исправить это, я предлагаю разработчикам по возможности использовать примитивные коллекции и особенно библиотеки Javalution.

  • Строковые операции немного медленные. Java использует неизменяемые строковые объекты в кодировке UTF-16 . Это означает, что вам нужно больше памяти, больше доступа к памяти, а некоторые операции сложнее, чем с ASCII (C, C ++). В то время это было правильное решение для мобильности, но оно стоило небольшой производительности. UTF-8 теперь выглядит лучше.

  • Доступ к массиву немного медленнее по сравнению с C из-за проверки границ. Раньше наказание было большим, но теперь маленьким (Java 7 оптимизирует множество избыточных проверок границ).

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

  • Java использует намного больше памяти, чем C, и если ваше приложение связано с памятью или с пропускной способностью памяти (кэширование и т. Д.), Это замедляет работу. Обратной стороной является то, что распределение / освобождение происходит быстро (высоко оптимизировано). Это свойство большинства языков высокого уровня в настоящее время, и связано с объектами и использованием GC, а не с явным распределением памяти. Плюс плохие библиотечные решения.

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

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

  • Обычно Java-приложения привязаны к очень старым версиям JVM. Особенно на стороне сервера. Эти старые JVM могут быть невероятно неэффективными по сравнению с последними версиями.

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


Однако есть несколько мест, где Java работает быстрее, чем большинство других языков:

  • Распределение и удаление памяти быстрая и дешевая. Я видел случаи, когда на 20% быстрее (или больше!) Выделять новый массив размером в несколько килобайт, чем повторно использовать кэшированный.

  • Инстанцирование объектов и объектно-ориентированные функции работают очень быстро (в некоторых случаях быстрее, чем C ++), потому что они разработаны с самого начала. Это частично из хорошего GC, а не явного распределения (что более удобно для большого количества небольших объектов). Можно написать код C, который превосходит это (путем гибкого управления памятью и эффективного выполнения malloc), но это нелегко.

  • Вызовы методов в основном бесплатны, а в некоторых случаях быстрее, чем код большого метода. HotSpot компилятор использует информацию о ходе выполнения для оптимизации вызовов методов и имеет очень эффективное встраивание. Используя дополнительную информацию о выполнении, он может иногда превосходить опережающие компиляторы и даже (в редких случаях) ручное встраивание. Сравните с C / C ++, где вызовы методов приводят к небольшому снижению производительности, если компилятор решает не включать его.

  • Синхронизация и многопоточность просты и эффективны. Java с самого начала была разработана с учетом потоков, и это видно. Современные компьютеры обычно имеют несколько ядер, и поскольку многопоточность встроена в язык, вы можете легко воспользоваться этим. В основном, увеличение скорости на 100–300% по сравнению со стандартным однопоточным C-кодом. Да, тщательно написанные C-потоки и библиотеки могут справиться с этим, но это большая дополнительная работа для программиста.

  • Строки включают длину: некоторые операции выполняются быстрее. Это лучше, чем использование строк, разделенных нулем (обычно в C). В Java 7 Oracle отказалась от оптимизации String.subString (), потому что люди использовали ее глупо и получали утечки памяти.

  • Копирование массива высоко оптимизировано. В последних версиях Java использует вручную настроенный ассемблер для System.arraycopy. Результатом является то, что в операциях с массивными копиями / memcopy, я видел, что мой код побеждает эквивалент в C на разумных полях.

  • JIT компилятор умен об использовании L1 / L2 кэша . Скомпилированные заранее программы не могут настроить свой код в режиме реального времени для конкретного процессора и системы, на которой они работают. JIT обеспечивает некоторые очень эффективные преобразования цикла таким образом.

Несколько других исторических фактов способствовали репутации "Java is slow":

  • До JIT-компиляции (Java 1.2 / 1.3) язык только интерпретировался, не компилировался и, следовательно, был очень медленным.
  • JIT-компиляция заняла время, чтобы стать эффективной (значительные улучшения с каждой версией)
  • Загрузка классов стала намного более эффективной за эти годы. Раньше он был довольно неэффективным и медленным во время запуска.
  • Код Swing и пользовательского интерфейса не очень хорошо использовал аппаратную графику.
  • Свинг просто ужасен. Я обвиняю AWT и Swing в том, что Java никогда не завоевывала популярность для настольных компьютеров.
  • Интенсивное использование синхронизации в библиотечных классах; теперь доступны несинхронизированные версии
  • Загрузка апплетов занимает целую вечность из-за передачи полного JAR-файла по сети и загрузки виртуальной машины для загрузки.
  • Синхронизация, используемая для значительного снижения производительности (оптимизирована для каждой версии Java). Отражение все еще дорого, хотя.
BobMcGee
источник
49
Object instantiation and object-oriented features are blazing fast to use (faster than C++ in many cases) because they're designed in from the beginning.и Collections are fast. Standard Java beats standard C/C++ in this area, even for most optimized C code.являются дикими утверждениями, не подкрепленными никакими доказательствами, связанными здесь.
Sjoerd
8
@Sjoerd - утверждения вряд ли дикие - они очевидны для меня и должны быть для любого, кто понимает различия в архитектуре системы памяти по умолчанию в C / C ++ и Java. Вы можете добиться гораздо больших успехов, если напишите свои собственные обработчики памяти (с такими вещами, как свободные списки, пулы памяти и т. Д.) Или используете библиотеку, которая реализует такое.
Рекс Керр
15
@Rex Kerr - Зачем использовать обработчики памяти, если вы можете использовать, например, стек для выделения ?! Вы путаете распределение кучи памяти с созданием объекта.
Sjoerd
20
@Rex Kerr - В основном вы утверждаете, что, поскольку все в Java включает в себя выделение памяти в куче, а также потому, что выделение Java в куче в Java быстрее, чем в C ++, все в Java быстрее. Вот некоторые новости для вас: в C ++ вы можете обойтись без выделения памяти в куче во многих случаях!
Sjoerd
10
@Sjoerd - Где я сказал, что все в Java быстрее? Просто прочитайте, что я сказал. Я сказал, что имел в виду, и уже рассмотрел все, что вы сказали в своем последнем комментарии.
Рекс Керр
49

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

  1. Медленное время запуска ВМ. Ранняя реализация Java требовала много времени для запуска и загрузки требуемых библиотек и приложения по сравнению с нативными приложениями.

  2. Медленный пользовательский интерфейс. Ранний свинг был медленным. Вероятно, не помогло то, что большинство пользователей Windows также находили Metal L & F уродливым.

Учитывая вышесказанное, неудивительно, что у людей сложилось впечатление «Ява медленная».

Для пользователей или разработчиков, привыкших к разработке собственных приложений или даже приложений Visual Basic , эти две точки являются наиболее заметными в приложении, и это первое впечатление, которое вы получите о приложении (если только это не приложение без графического интерфейса, в котором применяется только 1.).

Вы не будете убеждать пользователя в том, что «он выполняет код очень быстро», когда запуск приложения занимает 8 секунд, по сравнению с его старым приложением Visual Basic, которое запускается немедленно, даже если выполнение кода и время запуска могут вообще не быть связаны.

Испортить первое впечатление - отличный способ начать слухи и мифы. И слухи и мифы трудно убить.

Короче говоря, Java не медленная. Люди, имеющие «Java - медленное отношение», основаны на первых впечатлениях от Java более 10 лет назад.

н.у.к.
источник
3
Несколько лет назад Java была очень медленной, но в недавних тестах производительности она работает почти так же быстро, как C / C ++, а в некоторых ситуациях она работает быстрее.
ChadNC
23
Java-приложения на OSX 10.6 на моем Macbook запускаются намного медленнее, чем приложения, написанные на Objective-C. Какие доказательства быстрого запуска?
Zan Lynx
2
Декомпрессия не является проблемой производительности. Мой компьютер в 1992 году распаковывал исполняемые файлы при запуске программ, которые повысили производительность по сравнению с загрузкой более длинного файла с жесткого диска. Несоответствие между процессором и жестким диском значительно выросло за прошедшие годы. Однако существует проблема с использованием формата zip-архива для rt.jar (почему? !!!), и содержащиеся в нем файлы классов не связаны (орешки !!).
Том Хотин - tackline
5
@Zan: обратите внимание, что JVM для Mac OS X написана (или, по крайней мере, адаптирована) Apple. Sun потратила довольно много времени, чтобы ускорить запуск на платформах, которые они поддерживают (Windows, Linux и Solaris), но они не смогли сделать это для Mac OS x (так как они не поддерживают этот порт). Возможно, Mac не смог / не применил / не перенес все эти оптимизации на Mac OS X.
Joachim Sauer
1
Я не считаю Java медленным (я знаю производителя игр, который делает в них игры); просто плохо по причинам пользовательского интерфейса. Ни одно «обычное» Java-приложение, которое я видел, не имеет приличного, полностью работающего пользовательского интерфейса.
RCIX
40

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

Медлительность языка во многом зависит от ваших ожиданий «быстрого». Если вы считаете, что C # - быстрый, Java, конечно, тоже быстрый. Если ваша проблемная область связана с базами данных или полуобработкой в ​​реальном времени, Java, безусловно, тоже достаточно быстр. Если вы готовы масштабировать свое приложение, добавляя больше оборудования, Java, скорее всего, вам подойдет. Если вы считаете, что постоянное ускорение в масштабе 5-10 не стоит того, вы, скорее всего, будете считать Java быстрым.

Если вы выполняете численные вычисления для больших наборов данных или привязаны к среде исполнения, где ресурсы ЦП ограничены, где постоянное ускорение в масштабе 5-10 будет огромным. Даже увеличение скорости на 0,5 может означать сокращение на 500 часов для завершения вычислений. В этих случаях Java просто не позволяет вам получить этот последний ярд производительности, и вы, вероятно, считаете, что Java работает медленно.

Сами
источник
2
согласился, и +1 на весь пост, потому что вы представляете правильную точку зрения, однако, C ++, например, отличается от того, что его трудно отлаживать, и его легко отрубить, но редко я слышал о том, что C ++ слишком медленный как я слышал о Java.
Стефано Борини
33

Вы, кажется, задаете два довольно разных вопроса:

  1. Является ли Java действительно медленной, и если да, то почему?
  2. Почему Java воспринимается как медленная, хотя она быстрее, чем многие альтернативы?

Первый из них - это вопрос типа «как долго это веревка». Все сводится к вашему определению «медленный». По сравнению с чистым интерпретатором Java очень быстр. По сравнению с другими языками, которые (обычно) скомпилированы с каким-либо байт-кодом, затем динамически скомпилированы с машинным кодом (например, C # или что-либо еще в .NET), Java примерно на одном уровне. По сравнению с языками, которые обычно компилируются в чистый машинный код и в которых (часто большие) группы людей работают не над чем, кроме как над улучшением своих оптимизаторов (например, C, C ++, Fortran, Ada), Java неплохо справляется с некоторыми задачами, но в целом имеет тенденцию быть по крайней мере несколько медленнее.

Многое из этого связано, прежде всего, с реализацией - в основном, это сводится к тому, что пользователь ждет, пока запускается динамический / JIT-компилятор, поэтому, если у вас нет программы, которая достаточно долго запускается, она Трудно оправдать то, что компилятор тратит много времени на сложные оптимизации. Поэтому большинство компиляторов Java (и C #, и т. Д.) Не прикладывают больших усилий для действительно сложных оптимизаций. Во многих случаях речь идет не столько о том, какие оптимизации выполняются, сколько о том, где они применяются. Многие проблемы оптимизации являются законченными NP, поэтому время, которое они занимают, быстро увеличивается с масштабом проблемы, на которую делается атака. Один из способов сохранить время в разумных пределах - применять оптимизацию только к одной функции за раз. Когда только разработчик ждет компилятора, Вы можете позволить себе занять гораздо больше времени и применить ту же оптимизацию к гораздо большим частям программы. Аналогично, код для некоторых оптимизаций довольно волосатый (и поэтому может быть довольно большим). Опять же, поскольку пользователь ожидает, пока этот код загружается (а время запуска JVM часто является существенным фактором общего времени), реализация должна сбалансировать время, сэкономленное в одном месте, и потерянное в другом - и учитывая, как мало кода выигрыш от оптимизации волос, поддержание малого размера JVM обычно более выгодно.

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

В-третьих, большая часть кода, написанного на C ++ (и C, тем более), просто старше и более зрелой. Во многом он содержит ядро ​​подпрограмм, написанных десятилетия назад, когда дополнительное время на оптимизацию кода было нормальным, ожидаемым поведением. Это часто дает реальное преимущество в коде, который меньше и быстрее. C ++ (или C) получает признание за то, что код небольшой и быстрый, но на самом деле он гораздо больше является продуктом разработчика и ограничений времени написания кода. В некоторой степени это приводит к самоисполняющемуся пророчеству - когда люди заботятся о скорости, они часто выбирают C ++, потому что у него такая репутация. Они тратят дополнительное время и усилия на оптимизацию, и пишется новое поколение быстрого кода C ++.

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

Что касается второго вопроса, я думаю, что это во многом вопрос человеческой природы на работе. Несколько фанатиков делают довольно раздутые заявления о том, что Java невероятно быстр. Кто-то пробует это и находит, что даже тривиальная программа запускается за несколько секунд и чувствует себя медленной и неуклюжей, когда запускается. Мало кто, вероятно, потрудится проанализировать вещи, чтобы понять, что во многом это время запуска JVM и тот факт, что, когда они впервые пробуют что-то, ни один из кодов еще не был скомпилирован - часть кода интерпретируется, а некоторые компилируются, пока они ждут. Хуже того, даже если он работает достаточно быстро, внешний вид и внешний вид обычно будут казаться посторонними и неуклюжими для большинства пользователей, поэтому даже если объективные измерения показывают быстрое время отклика, он все равно будет выглядеть неуклюжим.

Добавление их вместе приводит к довольно простой и естественной реакции: Java медленная, безобразная и неуклюжая. Учитывая шумиху, которая говорит, что это действительно быстро, есть тенденция слишком остро реагировать и думать, что это ужасно медленно, а не (более точно) «немного медленнее, и это в основном при определенных обстоятельствах». Как правило, это хуже всего для разработчика, пишущего первые несколько программ на языке. Выполнение программы «hello world» на большинстве языков происходит мгновенно, но в Java есть легко заметная пауза, когда JVM запускается. Даже чистый интерпретатор, который работает намного медленнее в тесных циклах и все еще часто будет появляться быстрее для кода, подобного этому, просто потому, что он может быть загружен и начал выполняться немного раньше.

Джерри Гроб
источник
16

Это устаревшая информация с первых дней (середина и конец 1990-х) Java. Каждая основная версия Java имеет значительные ускорения по сравнению с предыдущей версией. С учетом того, что Oracle явно объединяет JRockit с JVM от Sun для Java 7, эта тенденция, похоже, будет продолжаться.

По сравнению со многими другими популярными современными языками (Python, Ruby, PHP), Java на самом деле значительно быстрее для большинства применений. Это не совсем соответствует C или C ++, но для многих задач это достаточно близко. Реальная проблема производительности должна заключаться в том, сколько памяти она использует.

Дэн Дайер
источник
14

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

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

В Java связывание происходит каждый раз при запуске приложения. Отсюда и долгое время запуска.

Были применены различные оптимизации, в том числе методы кэширования, и компьютеры становятся быстрее (и они становятся «быстрее», чем приложения «больше»), поэтому важность проблемы в последнее время значительно снизилась; но старые предубеждения остаются.

Что касается производительности впоследствии, мои собственные тесты на компактных вычислениях с доступом к массиву (в основном хеш-функциями и другими криптографическими алгоритмами) обычно показывают, что оптимизированный C-код примерно в 3 раза быстрее, чем Java-код; иногда C на 30% быстрее, чем Java, иногда C может быть в 4 раза быстрее, в зависимости от реализованного алгоритма. Я видел 10-кратный коэффициент, когда код «С» фактически собирался для большой целочисленной арифметики из-за кодов умножения 64x64-> 128, которые предлагает процессор, но Java не может использовать, потому что его самый длинный целочисленный тип - 64-битный long. Это крайний случай. В практических условиях соображения пропускной способности ввода-вывода и пропускной способности памяти не позволяют коду C работать в три раза быстрее, чем Java.

Томас Порнин
источник
Хм ... Я думал, что большинство библиотек C в настоящее время также динамически связаны. Или вы говорите о чем-то другом?
Шон Макмиллан
4
@Sean: динамическое связывание для C происходит для «внешних символов»: функций, которые используются в одной DLL и определены в другой. Типичное приложение C будет использовать дюжину DLL. Для Java динамическое связывание происходит для всех методов во всех классах: в типичном Java-приложении есть тысячи (включая стандартную библиотеку). В мире C большинство ссылок (все ссылки, которые не пересекают границу DLL) разрешаются во время компиляции, только небольшая часть остается во время выполнения.
Томас Порнин
14

Ява определенно медленная, особенно для количественной работы.

Я использую комбинацию R , Python и C / C ++ с оптимизированными многопоточными библиотеками ATLAS . На каждом из этих языков я могу умножить матрицу парных чисел 3000 на 3000 с собой примерно за 4 секунды. Используя Colt и Parallel Colt в Java, одна и та же операция займет 185 секунд! Удивительно, несмотря на то, что эти Java-библиотеки параллельны по своей природе.

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

Моя машина - HP Core 2 Duo с 3 ГБ оперативной памяти. Я использую 64-битную Ubuntu 10.04 (Lucid Lynx).

Хамаад Шах
источник
Исходя из вышеупомянутого комментария, я выполнил ту же операцию умножения матриц с использованием JAMA, и это заняло около 50 секунд. Все еще слишком медленно по сравнению с другими языками.
Хамаад Шах
7
Сколько времени заняла Java, когда вы выполняли умножение в библиотеках, вызываемых через JNI. Учитывая, что все, что вы можете делать в C / C ++, вы можете делать с JNI (добавьте несколько сотен мнано-секунд), запас относительно невелик. Я предполагаю, что ваше умножение матриц R и Python не было написано на R или Python, просто вызвано из этих языков.
Питер Лори
2
Из любопытства, вы выполнили какое-либо профилирование, чтобы определить, есть ли в вашем коде точка доступа (преобразование типов / автобокс)?
Торбьерн Равн Андерсен
10

Для опыта большинства людей , взаимодействующий с ним - Java является медленным. Мы все видели, как в нашем браузере кружится кофейная чашка, пока не появился апплет. Требуется время, чтобы раскрутить JVM и загрузить двоичные файлы апплета, и это влияет на восприятие пользователя таким образом, чтобы это было замечено.

Не помогает то, что медленное ускорение JVM и время загрузки апплета заметно обозначены кофейной чашкой Java, поэтому люди связывают ожидание с Java. Когда для загрузки Flash требуется много времени, разработчик Flash определяет фирменное наименование сообщения «загрузка», поэтому люди не винят технологию Flash в целом.

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

Спайк Уильямс
источник
9

Java имеет репутацию медленной, потому что она была медленной. В первых версиях Java компиляция Just In Time была либо отсутствует, либо, скорее, плохая. Это означало, что код, хотя и был байт-кодом, интерпретировался, поэтому даже для самых простых операций (таких как добавление двух целых чисел) машине приходилось выполнять все виды сравнений, разыменования указателей и вызовов функций. JIT-компилятор постоянно совершенствуется; сейчас наступает момент, когда, если я буду небрежно писать код C ++ и код Java, Java будет иногда превосходить C ++, потому что JIT-компилятор понимает, что у меня есть некоторая ненужная разыменование указателя, и позаботится обо мне.

Если вы хотите увидеть, насколько велика разница в компиляции JIT, посмотрите интерпретированные и не интерпретированные тесты в игре Computer Languages ​​Benchmark Game . (Pidigits использует внешнюю библиотеку для выполнения всех вычислений, поэтому тест не меняется; другие показывают ускорение в 6-16 раз!)

Итак, это главная причина. Существует множество других, менее важных причин, которые не помогли решить проблему: изначально время запуска Java было медленным (теперь исправлено); загрузка веб-приложений на Java занимает много времени (гораздо менее актуально сейчас с широко доступным широкополосным доступом и с такими большими вещами, как фильмы); UI Swing не был (и до сих пор не написан) с точки зрения производительности, поэтому он гораздо менее быстр, чем эквиваленты, например, в C ++.

Рекс Керр
источник
6

Ява была медленной, назад в тот же день. Это стало намного быстрее благодаря нескольким поколениям улучшений производительности . Последнее, что я слышал, это обычно в пределах 10% от скорости C # - иногда быстрее, иногда медленнее.

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

Кроме того, есть по крайней мере несколько человек , которые никогда не поверят в жизнеспособность Java.

Калеб Бразе
источник
1
К сожалению, запуск JVM все еще намного медленнее, чем запуск CLR. Это связано с тем, что Sun выпустила Java 7 худшим образом, поэтому мы застряли с инкрементными исправлениями для 4-летней Java 6.
BobMcGee,
3
Ух, Java 6 4 года ??? Да, я так думаю (если вы считаете бета). Все еще чувствует себя новым для меня - я просто перестал использовать 1.4 на работе.
Kaleb Brasee
Java 1.4 является пригодной для использования, но отчасти неприхотливой, так как 1.5 и 1.6 добавили много повышения производительности и синтаксического сахара. С тех пор были введены оптимизации Bounds-check и System.arraycopy. Так было много улучшений синхронизации. Я думаю, что честно сказать, что 1.4 действительно медленный.
BobMcGee
LOL, я знаю - каждый раз, когда мне приходится выполнять итерации вручную или использовать массив вместо общего списка, я хочу разбить свой ноутбук пополам ... У IBM фактически была Java 5, доступная на WAS 6.1 в течение многих лет, но я ' Я застрял на WAS 6.0 :( Я использую Java 5/6 с тех пор, как она вышла для моих собственных задач, но я ограничен только старыми версиями сервера в работе. Производительность в процентах от двузначного числа улучшена с 1.4 до новейших версий для многих вещей, и я с нетерпением жду их.
Kaleb Brasee
6

Стефано:

Я был с Java с самого начала, поэтому, с моей точки зрения, слава о медлительности была создана невосприимчивыми и медленными внешними интерфейсами GUI (AWT, а затем Swing) и в Applets, вероятно, из-за дополнительного медленного времени запуска ВМ.

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

Java на бэкэнде и вычислительном уровне не такие медленные. Кольт является одним из лучших примеров:

Последний стабильный выпуск Colt преодолевает барьер 1,9 Гфлоп / с на JDK ibm-1.4.1, RedHat 9.0, 2x IntelXeon @ 2.8 ГГц.

Есть много вещей за пределами основной Java, которые следует учитывать, такие как Realtime Java или специальные механизмы для повышения скорости, такие как Javolution , а также компиляция Ahead-Of-Time (например, gcj). Кроме того, существуют микросхемы, которые могут выполнять Java-байт-код напрямую, как, например, тот, который есть в текущих iPhone и iPod ARM Jazelle .

Я думаю, что в целом сегодня это политическое решение (например, отсутствие поддержки Java на iPhone / iPod) и решение против Java как языка (потому что многие считают его слишком многословным).

Однако в настоящее время для Java VM существует множество других языков (например, Python, Ruby, JavaScript, Groovy, Scala и т. Д.), Которые могут быть альтернативой.

Лично я продолжаю пользоваться ею как гибкой и надежной платформой с отличными инструментами и доступностью библиотек, которая позволяет работать со всем, от самого маленького устройства (например, JavaCard) до самых больших серверов.

Dieter
источник
Итак, еще одна плохая репутация пришла из инструментария GUI. Конечно, я предполагаю, что, поскольку современная JVM использует собственные виджеты, они подключаются к библиотекам ОС, верно? или они используют AWT / Swing для визуализации внешнего вида платформы хоста?
Стефано Борини
Стефано: Swing на самом деле основан на идее универсального рендеринга виджетов, не относящихся к нативным, поэтому вы предполагаете, что это неправильно. Это действительно «подключаемый стиль», который позволяет компонентам Swing эмулировать внешний вид собственных компонентов. Если вы ищете что-то подобное, вы можете попробовать SWT ( eclipse.org/swt ), который действительно подключится к родной ОС и будет использовать собственные виджеты с использованием JNI (который считается узким местом).
Дитер
Java2D (используется для Swing) очень быстр в наши дни, и использование нативных виджетов (SWT) не дает никакого преимущества в производительности. По крайней мере, это то, что я прочитал, когда решал, изучать ли Swing или SWT 6 месяцев назад.
Луиджи Плинге
4

Молоток гораздо медленнее раскатывает тесто, чем многие другие инструменты. Не делает молот «медленным» и не менее полезным для задач, для которых он предназначен.

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

Но когда дело доходит до «приложений реального мира», Java часто является правильным инструментом. Тем не менее, ничто не помешает разработчикам сделать медленное решение с использованием ЛЮБОГО инструмента. Злоупотребление инструментом - хорошо известная проблема (просто посмотрите на репутацию PHP и VB). Тем не менее, чистый (в основном) чистый дизайн и синтаксис Java делают многое для уменьшения злоупотреблений.

mobiGeek
источник
3

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

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

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

  3. Другим способом, которым Java является языком высокого уровня, является сборщик мусора . Сборка мусора может выполняться медленнее, чем mallocи freeдля программ, которые выделяют сразу всю необходимую память и работают с этим. Проблема заключается в том, что в языках, где отсутствует сборщик мусора, программисты, как правило, пишут только программы, которые выделяют всю необходимую им память сразу, и терпят неудачу, если оказывается, что какая-то произвольная константа максимального размера была переполнена. Так что сравнение яблок с апельсинами. Когда программисты прилагают усилия для написания и отладки программ с динамическим размещением цепочечных структур на языках, отличных от GC, они иногда обнаруживают, что их программы работают не быстрее, чем на языке GC, потому что mallocиfreeне бесплатны! У них тоже есть накладные расходы ... Кроме того, отсутствие GC заставляет указывать, кто что освобождает, и необходимость указывать, кто освобождает то, что, в свою очередь, иногда заставляет вас делать копии - когда нескольким функциям понадобятся данные, и неясно, какие будет использовать его в последний раз - тогда как копирование не было бы необходимо на языке GC.

Паскаль Куок
источник
1. Вероятно, не правда с HotSpot. 2. Только если вы пометите метод как синхронизированный.
Уинстон Эверт
1
1. Компилятор не оптимизирует код, но JVM достаточно умен, чтобы динамически определять, что обычно вызывается только один или два виртуальных метода, и может вызывать их статически или даже встроенно. Я уверен, что C ++ не может встроить виртуальные методы. 2. Каждый Java-объект имеет блокировку. Он имеет небольшие накладные расходы (около байта) на каждый объект, но имеет небольшое влияние, если не используется. 3. В Java вы можете выделить сразу все необходимые вам объекты. Это может дать вам приложение, которое не GC весь день. ;) Java GC неявно многопоточный, что требует специальных библиотек на C ++.
Питер Лори
C ++ может встроить виртуальные вызовы, но Java может делать это в большем количестве случаев, а также эффективнее с оптимизацией мегаморфных сайтов вызовов.
Петр Колачковский
2

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

Кен Лю
источник
было ли это связано с технологией GC? Я знаю, что у них есть некоторые стратегии (например, слои поколений для объектов), чтобы быть более эффективными на этапе ГХ. Какова была стратегия в то время?
Стефано Борини
1
Эксперт IANA JVM, но я думаю, что в то время для GC использовался однопоточный алгоритм метки / развертки, который требовал приостановки всей JVM во время выполнения GC. В настоящее время в JVM есть одновременная оценка / развертка, а также множество других улучшений производительности.
Кен Лю
2
Современные алгоритмы GC хороши, но я думаю, что самым большим улучшением стал JIT.
Паскаль Тивент
1

Многие Java-приложения для настольных систем (в наше время такие вещи, как Eclipse) имеют плохую отзывчивость GUI, вероятно, из-за высокого потребления памяти и того факта, что classloader может выполнять много операций ввода-вывода. Это улучшается, но было хуже несколько лет назад.

Многие (большинство) люди любят делать обобщения, поэтому они говорят «Java медленный», потому что они чувствуют, что приложения работают медленно, когда они взаимодействуют с ними.

Войцех Качмарек
источник
Как вы думаете, высокое потребление памяти происходит из-за инструмента или из библиотек Java?
Стефано Борини
В случае Eclipse - из самой инфраструктуры Eclipse. То же самое для «тяжелых» GUI в прошлом (JBuilder, насколько я помню). У меня есть ощущение, что это потому, что для использования архитектуры плагинов (например, Eclipse) на статически типизированном языке необходимо множество шаблонных объектов. Emacs также имеет плагины, и его потребление памяти в 10-20 раз меньше, чем у Eclipse при обычном кодировании. Код Emacs Lisp компилируется в байт-код и загружается в экземпляр emacs, а затем запускается - подобно загрузчику классов Java. Я предполагаю, что в Java есть тонны промежуточных объектов, созданных для обеспечения некоторой подключаемости.
Войцех Качмарек
1

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

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

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

Турбьерн Равн Андерсен
источник
1

Как говорит Паскаль, Java не уступает другим языкам высокого уровня. Тем не менее, как кто-то, кто работал с оригинальными JVM на Windows 98 , в то время уровень абстракции, предоставляемый виртуальной машиной Java, был, скажем так, болезненным.

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

Каски
источник
0

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

Или, возможно, «люди идиоты» - лучший ответ.

Мистер Бой
источник
0

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

helpermethod
источник
6
Я думаю что ты имели в виду , чтобы сказать, что JIT-компилируется (не интерпретируется) код будет бить АОТ код. Интерпретация всегда будет медленнее, чем выполнение скомпилированного кода. Вот почему используются JIT-компиляторы. Подвох: разница между опережающим временем компилятором и JIT-компилятором невелика, за исключением того, что JIT-компилятор должен компилироваться быстрее и может использовать информацию времени выполнения для подсказок по оптимизации. Компиляторы AoT для конкретной платформы с оптимизацией для конкретной платформы будут почти всегда превосходить JIT, потому что нет предела тому, сколько времени они тратят на оптимизацию.
BobMcGee
Спасибо за ответ, никогда не задумывался о том, сколько времени JIT-компиляторы имеют в своем распоряжении.
helpermethod
Вы имеете в виду что-то вроде адаптивной оптимизации горячей точки?
Стефано Борини
2
@BobMcGee: Очень верно. Программа C ++ может быть создана для медленной работы с обратной связью профиля для всех своих операций. Тогда компилятор может перестроить очень быструю версию, используя полчаса процессорного времени и 2 ГБ оперативной памяти. JIT, который сделал это, заставил бы пользователей уйти.
Зан Рысь
1
Время компиляции JIT незначительно для долго работающих приложений, таких как серверы. AOT с PGO более ограничен по сравнению с JIT по крайней мере по двум причинам. Во-первых, большая разница в производительности достигается за счет легких оптимизаций. Сравните gcc -O2 с gcc -O3. В большинстве случаев нет никакой разницы , иногда -O3 может быть немного лучше, иногда немного хуже, но я никогда не испытывал> 2х разницы с этим. Во-вторых, используя AOT даже с PGO, вы можете только догадываться, какой профиль будет на сайте использования. Угадай неправильно, и ты далеко позади JIT. И фактический профиль может быть чрезвычайно зависимым от конфигурации.
Петр Колачковский