Чи справді Java повільна?


180

Java має певну ступінь репутації за те, що вона повільна .

  • Чи справді Java повільна?
  • Якщо так, то чому? Де (або було) вузьке місце? Це через неефективні СВМ? Збір сміття? Чисті бібліотеки байт-кодів, а не оброблений JNI код C? Багато інших мов мають ці функції, але вони не мають такої репутації повільності.

35
люди так нервують ... не бачать, як це може бути суб'єктивним, ні це аргументативно. Цікаво, якщо питання на кшталт "чому сортування бульбашок повільний" отримав би такий же результат. Я задавав технічне запитання і хотів отримати технічні відповіді (які я отримав), але закривати питання як суб'єктивне та аргументативне - смішно.
Стефано Борині

1
Я прочитав більшість найпопулярніших коментарів, і жоден з них не враховує дивовижного факту, що настільні додатки на основі C # GUI працюють набагато швидше, ніж будь-які настільні додатки на базі Java GUI, включаючи сучасні.
BobTurbo

3
Оскільки веб-розробник на стороні клієнта, який мав справу з .net веб-формами, .net MVC, PHP, Rails, Django та широким розмаїттям всього, окрім Spring (про що я чув, що це добре) на Java, я очікую погану продуктивність / архітектуру із задніх кінців, побудованих командами Java. Я підозрюю, що справжня проблема - це не орієнтири, а швидше питання про те, що там просто є лайно посередніх Java-розробників. Це не вина мови. Це не вина Java-розробників, які насправді відточують своє ремесло і вивчають інші мови, крім Java. Однак це може бути вина Sun, Certs, 90-х та ІТ-індустрії взагалі.
Ерік Реппен

Відповіді:


236

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

Якщо ви все ще вважаєте, що Java повільна , перегляньте результати гри з орієнтирами . Щільно оптимізований код, написаний заздалегідь складеною мовою (C, Fortran тощо), може перемогти його; однак Java може бути швидкішою за 10 разів, як PHP, Ruby, Python тощо. Існують конкретні області, де вона може перемогти загальні компільовані мови (якщо вони використовують стандартні бібліотеки).

Зараз немає приправ для "повільних" програм Java. Винні розробники та застарілий код / ​​бібліотеки, набагато більше, ніж мова. Крім того, звинувачуйте в чому-небудь "підприємство".

Справедливості до натовпу "Ява повільно", ось такі сфери, де вона все ще повільна (оновлено на 2013 рік):

  • Бібліотеки часто пишуться для "правильності" та читабельності, а не виконання. На мою думку, це головна причина, чому Java все ще має погану репутацію, особливо на сервері. Це робить проблеми String експоненціально гіршими. Деякі прості помилки поширені: об'єкти часто використовуються замість примітивів, знижуючи продуктивність і збільшуючи використання пам'яті. Багато бібліотек Java (включаючи стандартні) створюватимуть рядки часто, замість того, щоб повторно використовувати змінні або більш прості формати (char [] або StringBuffer). Це повільно і створює тонни сміття, які збирають пізніше. Щоб виправити це, я пропоную розробникам використовувати примітивні колекції та, особливо, бібліотеки Javalution, де це можливо.

  • Струнні операції трохи повільні. Java використовує незмінні рядкові об'єкти, кодовані UTF-16 . Це означає, що вам потрібно більше пам'яті, більше доступу до пам'яті, а деякі операції складніші, ніж для ASCII (C, C ++). У той час це було правильне рішення для портативності, але воно несе в собі невелику вартість продуктивності. UTF-8 зараз виглядає кращим вибором.

  • Доступ до масиву є дещо повільнішим порівняно з C, через перевірку меж. Штраф раніше був великим, але зараз невеликим (Java 7 оптимізує багато зайвих перевірок меж).

  • Відсутність довільного доступу до пам'яті може зробити деяку обробку вводу / виводу та бітовим рівнем повільною (наприклад, стиснення / декомпресія). Це функція безпеки більшості мов високого рівня зараз.

  • Java використовує на багато більше пам'яті, ніж на C, і якщо ваша програма обмежена пам'яттю або обмежена смуга пропускання пам'яті (кешування тощо), це робить її повільніше. Зворотний бік полягає в тому, що розподіл / угода розташування швидко палає (дуже оптимізовано). Це особливість більшості мов на високому рівні зараз, і це пояснюється об'єктами та використанням GC, а не явним розподілом пам'яті. Плюс погані рішення бібліотеки.

  • Введення / виведення на основі потоків відбувається повільно через (IMO, поганий вибір), що вимагає синхронізації для кожного доступу до потоку. NIO це виправило, але це біль. Можна обійти це, виконуючи читання / запис у масив, а не елемент за один раз.

  • Java не забезпечує такі самі низькорівневі функціональні можливості, як і C, тому ви не можете використовувати брудні вбудовані трюки асемблера, щоб зробити деякі операції швидше. Це забезпечує мобільність і є функцією більшості мов високого рівня зараз.

  • Загальноприйняте бачити програми Java, прив'язані до дуже старих версій JVM. Особливо на стороні сервера. Ці старі JVM можуть бути неймовірно неефективними порівняно з останніми версіями.

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


Однак є кілька місць, де Java швидша, ніж у більшості інших мов:

  • Розподіл пам’яті та їх розподіл швидко і дешево. Я бачив випадки, коли на 20% швидше (або більше!) Виділити новий масив з декількома кБ, ніж використовувати кешований повторно.

  • Об’єктні об'єктивні та об'єктно-орієнтовані функції швидко використовуються (швидше, ніж C ++ в деяких випадках), оскільки вони розроблені з самого початку. Частково це сприятливо для GC, а не явного розподілу (що є більш прихильним для безлічі невеликих виділень об'єктів). Можна кодувати C, який перемагає це (прокручуючи спеціальне управління пам’яттю та роблячи malloc ефективно), але це непросто.

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

  • Синхронізація та багатонарізка прості та ефективні. Java була створена так, щоб вона була зрозумілою для початку, і це показує. У сучасних комп’ютерах зазвичай є декілька ядер, і оскільки нитка вбудована в мову, ви можете дуже легко скористатися. По суті, додаткове збільшення швидкості на 100% до 300% порівняно зі стандартним однопотоковим кодом C. Так, ретельно написана C нарізка і бібліотеки можуть це перемогти, але це багато зайвої роботи для програміста.

  • Рядки включають довжину: деякі операції проходять швидше. Це б'ється за допомогою рядків з обмеженим нулем (поширене в С). У Java 7 Oracle зняв оптимізацію String.subString (), оскільки люди тупо використовували її та отримували витоки пам'яті.

  • Копія масиву дуже оптимізована. У останніх версіях Java використовує вручну налаштований асемблер для System.arraycopy. Результат полягає в тому, що в операціях arraycopy / memcopy-важких я бачив, як мій код бив еквівалент в C за розумними полями.

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

Кілька інших історичних фактів сприяли репутації "Ява повільно":

  • Перед компіляцією JIT (Java 1.2 / 1.3) мова інтерпретувалася лише не, а не компільована і, таким чином, дуже повільна.
  • Компіляція JIT потребувала часу, щоб стати ефективною (основні вдосконалення для кожної версії)
  • Завантаження класів з часом стало набагато ефективнішим. Це було досить неефективно і повільно під час запуску.
  • Swing та UI-код не дуже добре використовували вбудовану графічну техніку.
  • Гойдалка просто жахлива. Я звинувачую AWT та Swing у тому, що Java ніколи не зациклювалася на робочому столі.
  • Сильне використання синхронізації в бібліотечних класах; несинхронізовані версії тепер доступні
  • Аплетти вічно завантажуються через передачу повної JAR по мережі та завантаження VM для завантаження.
  • Синхронізація застосовується для виконання суворого покарання (це було оптимізовано для кожної версії Java). Хоча роздуми все ще дорогі.

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 дуже швидка. У людей, з якими я говорив, враження про повільність Яви походить з двох речей:

  1. Повільний час запуску VM. Рання реалізація Java зайняла багато часу, щоб запустити та завантажити потрібні бібліотеки та додаток порівняно з рідними програмами.

  2. Повільний інтерфейс користувача. Рання гойдалка була повільною. Це, мабуть, не допомогло, що більшість користувачів Windows вважають Metal L&F за замовчуванням також некрасивим.

З огляду на вищезазначені моменти, не дивно, що люди справили враження на «Ява повільно».

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

Ви не переконаєте користувача, що "він виконує код дуже швидко", коли програмі потрібно 8 секунд, щоб запустити проти його старого додатка Visual Basic, яке запускається негайно - навіть якщо виконання коду та час запуску можуть бути зовсім не підключені.

Зруйнувати перше враження - це чудовий спосіб запустити чутки та міфи. І чутки і міфи важко вбити.

Словом, Java не повільна. Люди, які мають "Ява повільне ставлення", грунтуються на перших враженнях від Java більше 10 років тому.


3
Кілька років тому Java була дуже повільною, але в останніх тестах на еталонні вона працює майже так само швидко, як C / C ++, а в деяких ситуаціях працює швидше.
ChadNC

23
Програми Java на OSX 10.6 на моєму Macbook запускаються набагато повільніше, ніж програми, написані в Objective-C. Що свідчить про швидкий час запуску?
Зан Лінкс

2
Декомпресія - абсолютно не проблема продуктивності. Мій комп’ютер у 1992 р. Декомпресував виконувані файли при запуску програм, які покращували продуктивність при завантаженні більш тривалого файлу з жорсткого диска. Різниця між процесором та жорстким диском сильно зросла протягом останніх років. Однак існує проблема з використанням формату zip-архіву для rt.jar (чому? !!!), а файли класу, що містяться, не пов'язані (гайки !!).
Том Хоутін - таклін

5
@Zan: зауважте, що JVM для Mac OS X написана (або принаймні адаптована) Apple. Sun вклала досить багато часу, щоб зробити час запуску швидшим на платформах, які вони підтримують (Windows, Linux та Solaris), але вони не змогли зробити це для Mac OS x (оскільки вони не підтримують цей порт). Можливо, Mac не зміг / не застосував / не переніме всі ті оптимізації до Mac OS X.
Йоахім Зауер

1
Я не вважаю, що Java є повільною (я знаю виробника ігор, який робить в них ігри); просто погано з причин користувальницького інтерфейсу. Жоден «звичайний» додаток Java, який я бачив, не має гідного, повністю працюючого інтерфейсу.
RCIX

40

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

Повільність мови багато в чому залежить від того, які ваші очікування щодо "швидкої". Якщо ви вважаєте, що C # є швидким, Java, безумовно, також швидкий. Якщо ваш проблемний домен пов’язаний з базами даних або напівфабрикатами в режимі реального часу, Java, безумовно, також досить швидка. Якщо ви раді масштабувати свою програму, додавши більше обладнання, Java, швидше за все, швидко для вас. Якщо ви вважаєте, що постійне прискорення коефіцієнта в масштабі 5-10 не варто, ви, швидше за все, вважаєте Java швидким.

Якщо ви робите чисельні обчислення на великих наборах даних, або пов'язані з середовищем виконання, де ресурси CPU обмежені, де постійне прискорення в масштабі 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 # тощо) не докладають великих зусиль для дійсно складних оптимізацій. У багатьох випадках менше стосується оптимізації, ніж де вони застосовуються. Багато проблем з оптимізацією не завершені, тому час, який вони займають, швидко зростає, коли розмір проблеми атакується. Один із способів утримати час в межах розуму - застосовувати оптимізацію лише до чогось, наприклад, однієї функції. Коли на розробник чекає лише розробник, ви можете дозволити собі зайняти набагато довше і застосувати цю саму оптимізацію до набагато більших фрагментів програми. Так само код деяких оптимізацій досить волохатий (і тому може бути досить великим). Знову ж таки, оскільки користувач чекає, поки цей код завантажується (а час запуску JVM часто є важливим фактором загального часу), реалізація повинна збалансувати час, збережений в одному місці, проти втраченого в іншому - і враховуючи, наскільки мало коду вигоди від волохатих оптимізацій, утримування JVM невеликим, як правило, вигідніше.

Друга проблема полягає в тому, що з Java ви часто отримуєте більш-менш "один розмір, який відповідає всім". Наприклад, для багатьох розробників Java Swing, по суті, є єдиною доступною бібліотекою вікон. У чомусь на зразок C ++ є буквально десятки бібліотек вікон, програмних програм тощо, кожна зі своїм набором компромісів між простотою використання та швидким виконанням, послідовним виглядом і відчуттям проти рідного вигляду та ін. Єдиним справжнім моментом є те, що деякі (наприклад, Qt) можуть бути досить дорогими (принаймні для комерційного використання).

По-третє, багато коду, написаного на C ++ (і тим більше C), просто старше і зріліше. У великій кількості він містить ядро ​​процедур, написане десятиліттями тому, коли витрачати додатковий час на оптимізацію коду було нормальною, очікуваною поведінкою. Це часто має реальну користь у коді, який менший та швидший. C ++ (або C) отримує кредит за те, що код є малим і швидким, але це набагато більше продукту розробника і обмежень часу написання коду. До певної міри це призводить до самореалізованого пророцтва - коли люди піклуються про швидкість, вони часто вибирають C ++, оскільки він має таку репутацію. Вони вкладають додатковий час і зусилля на оптимізацію, і нове покоління швидкого C ++ коду пишеться.

Підводячи підсумок, звичайна реалізація Java робить максимальну проблему оптимізації в кращому випадку. Гірше, де видно Java , такі речі, як набори інструментів для вікон та час запуску JVM, часто грають більшу роль, ніж швидкість виконання мови в будь-якому випадку. У багатьох випадках C і C ++ також отримують заслугу за те, що насправді є продуктом просто працюючи більше при оптимізації.

Щодо другого питання, я думаю, що це багато в чому справа людської натури. Кілька завзятостей висловлюють досить завищені твердження про те, що Ява сліпуче швидка. Хтось випробовує це і виявляє, що навіть тривіальна програма потребує декількох секунд, щоб почати, і відчуває себе повільно і незграбно, коли вона працює. Мало хто, мабуть, переймається аналізом речей, розуміючи, що велика частина цього - час запуску JVM, і той факт, що, коли вони вперше випробують, ще жоден код не був складений - частина коду інтерпретується, а деякі складаються, поки вони чекають. Гірше, що навіть коли вона працює досить швидко, зовнішній вигляд зазвичай здається стороннім і незграбним для більшості користувачів, тому навіть якщо об’єктивні вимірювання показали швидкий час відгуку, він все ще здасться незграбним.

Додавання їх разом призводить до досить простої і природної реакції: що Java повільна, потворна і незграбна. Враховуючи ажіотаж, який говорить, що це дуже швидко, є тенденція до надмірної реакції та висновку, що вважають це жахливо повільним, а не (більш точним) "трохи повільніше, і це переважно за конкретних обставин". Це, як правило, найгірше для розробника, який пише перші кілька програм мовою. Виконання програми "привіт світ" на більшості мов видається миттєвим, але в 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. Це крайній випадок. У практичних умовах міркування пропускної здатності вводу / виводу та пам'яті запобігають дійсності коду С утричі швидше, ніж Java.


Хм ... я думав, більшість бібліотек С також динамічно пов'язані і в наш час. Або ви говорите про щось інше?
Шон Макміллан

4
@Sean: динамічне посилання на C відбувається для "зовнішніх символів": функції, які використовуються в одній DLL та визначені в іншій. Типовий додаток C використовуватиме десяток DLL. Для Java відбувається динамічне посилання для всіх методів у всіх класах: у типовому додатку Java є тисячі (у тому числі у стандартній бібліотеці). У світі C більшість зв'язків (усі посилання, які не перетинають межу DLL) вирішуються під час компіляції, лише невелика частка залишається робити під час виконання.
Томас Порнін

14

Java, безумовно, повільна, особливо для кількісної роботи.

Я використовую комбінацію 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
Чи не цікаво, чи зробили ви якісь профілі, щоб визначити, чи є у вас кодова точка доступу (тип конверсії / автобоксинг)?
Thorbjørn Ravn Andersen

10

Для більшості людей, які взаємодіють із ним, Java - повільна. Ми всі бачили, що чашка кави крутиться на нашому браузері, перш ніж з’явиться якийсь аплет. Виділення JVM та завантаження бінарних файлів аплетів потребує певного часу, і це впливає на користувацький досвід таким чином, як це помічено.

Це не допомагає, що повільний час JVM-завантаження та завантаження аплетів помітно позначається чашкою кави Java, тому люди пов'язують очікування з Java. Коли для завантаження Flash потрібно тривалий час, розробник Flash визначає брендування повідомлення про "завантаження", тому люди не звинувачують Flash-технологію в цілому.

Все це не має нічого спільного з продуктивністю Java на сервері або з багатьма іншими способами, якими Java звикає поза браузером. Але це те, що бачать люди, і що пам'ятають розробники, які не є Java, коли думають про Яву.


9

Java має репутацію повільної, тому що вона була повільною. Перші версії Java не мали або не дуже погану компіляцію Just In Time. Це означало, що код, хоча і байт-код, інтерпретується, тому навіть для найпростіших операцій (наприклад, додавання двох цілих чисел) машина повинна була робити всілякі порівняння та перенаправлення покажчиків та викликів функцій. Компілятор JIT постійно вдосконалювався; тепер справа в тому, що якщо я пишу безтурботно код C ++, а Java-код недбало, Java іноді перевершує C ++, оскільки компілятор JIT розуміє, що у мене є непотрібна перенаправлення покажчика, і піклується про нього за мене.

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

Отже, це основна причина. Існує безліч інших, менших причин, які не допомогли вирішити питання: спочатку час запуску Java був повільним (тепер виправлено); веб-додатки на Яві потребують тривалого завантаження (набагато менш актуально зараз із широкодоступною широкосмуговою мережею та з великими речами, такими як фільми, які очікуються); Swing Swing не був (і досі не є) написаний з врахуванням продуктивності, тому він набагато менш спритний, ніж еквіваленти, наприклад, C ++.


6

Java була повільною, назад у той день. Це стало набагато швидше, через кілька поколінь підвищення продуктивності . Востаннє я чув, як правило, це в межах 10% від швидкості C # - іноді швидше, іноді повільніше.

Запуск аплету Java все ще повільний, оскільки ви повинні запустити цілий JVM, який повинен завантажувати всі його класи. Дещо як завантаження іншого комп’ютера. Як тільки JVM запускається, це відбувається досить швидко, але запуск - це зазвичай те, що люди пам’ятають.

Також є щонайменше кілька людей, які ніколи не повірять у життєздатність Java.


1
На жаль, запуск JVM все ще набагато повільніше, ніж запуск CLR. Це тому, що Sun витягнув ноги найгіршим чином, випускаючи Java 7, тому ми застрягли з поступовими виправленнями до 4-річної Java 6.
BobMcGee

3
Нічого, Яві 6 років 4? Так, я думаю, що так (якщо порахувати бета-версію). Все ще відчуває себе новим - я просто перестав використовувати 1.4 на роботі.
Kaleb Brasee

Java 1.4 є корисним, але виглядає суктастичним, оскільки 1.5 та 1.6 додають багато підвищення продуктивності та синтаксичний цукор. З тих пір були введені оптимізація меж та перевірка системних систем. Так було багато покращень синхронізації. Я думаю, що справедливо сказати, що 1.4 справді є повільним.
BobMcGee

LOL, я знаю - щоразу, коли мені доводиться повторювати вручну або використовувати масив замість загального списку, я хочу розбити свій ноутбук навпіл ... IBM фактично вже протягом року використовувала Java 5 на WAS 6.1, але я ' я застряг на WAS 6.0 :( Я використовував Java 5/6 з тих пір, як з'явився для моїх власних речей, але я просто обмежений старими версіями сервера на роботі. Є двозначні покращення продуктивності від 1,4 до найновіших версій на багато речей, і я з нетерпінням чекаю їх
Калеб Брезе

6

Стефано:

Я був з Java з самого початку, тому, з моєї точки зору, слава повільності була створена невідповідними і повільними інтерфейсами графічного інтерфейсу (AWT, а потім Swing) і в Applets, ймовірно, через додаткові повільні періоди запуску ВМ.

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

Java на початковому та обчислювальному рівнях не така повільна. Кольт - один з найкращих прикладів:

Останній стабільний реліз Colt долає бар'єр 1.9 Gflop / s на JDK ibm-1.4.1, RedHat 9.0, 2x IntelXeon@2.8 ГГц.

За межами основної Java є багато речей, які слід враховувати, як Java в реальному часі або спеціальні механізми для підвищення швидкості, як Javolution , а також компіляція Ahead-Of-Time (наприклад, gcj). Також є ІС, які можуть виконувати Java Bytecode безпосередньо, як, наприклад, той, який є у поточних iPhone та iPod Jazelle на iPod .

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

Однак сьогодні існує багато інших мов для Java VM (наприклад, Python, Ruby, JavaScript, Groovy, Scala тощо), які можуть бути альтернативою.

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


Гаразд, ще одна погана репутація виникла з інструментарію GUI. Звичайно, я припускаю, що оскільки сучасний JVM використовує вбудовані віджети, вони підключаються до бібліотек ОС, правда? або вони використовують AWT / Swing для надання однакового зовнішнього вигляду хост-платформи?
Стефано Борині

Стефано: Swing насправді базується на ідеї універсального відерування віджетів, тому ваше припущення - це неправильно. Це дійсно механізм "підключення зовнішнього вигляду і відчуття", який дозволяє компонентам Swing імітувати зовнішній вигляд нативних компонентів. Якщо ви шукаєте щось подібне, ви, можливо, захочете перевірити SWT ( eclipse.org/swt ), який дійсно зачепить у рідну ОС та використовувати вбудовані віджети за допомогою JNI (що, як кажуть, є вузьким місцем).
Дітер

Java2D (використовується для Swing) в наші дні дуже швидкий, а використання вбудованих віджетів (SWT) не дає користі від продуктивності. Принаймні, це я читав, коли вирішував навчатись Swing чи SWT 6 місяців тому.
Луїджі Плінге

4

Молоток набагато повільніше розкачує тісто, ніж багато інших інструментів. Це не робить молоток "повільнішим", і не менш корисним для завдань, які він призначений для виконання.

Як загальна мова програмування, Java нарівні з багатьма (якщо не більшістю) для широкого набору завдань програмування. Існують специфічні, тривіальні тести, для яких Java не перевершує рукотворні рішення на менш складних мовах - ті, що «ближче до металу».

Але якщо мова йде про "реальні програми", то Java часто є правильним інструментом. Тепер, зазначаючи це, ніщо не завадить розробникам приймати рішення, що працює на повільній основі, використовуючи будь-який інструмент. Неправильне використання інструменту - добре відома проблема (просто подивіться на репутацію PHP та VB). Однак чистий дизайн та синтаксис Java (здебільшого) робить багато, щоб зменшити зловживання.


3

Java - мова високого рівня, і її репутація нині має продуктивність нарівні з іншими, порівнянними мовами високого рівня.

  1. Він має динамічну семантику зв’язування . У порівнянні з C ++, де невіртуючі методи компілюються як виклики функцій, навіть найкращий компілятор Java у світі повинен створювати менш ефективний код. Але це також більш чистий, семантичний на високому рівні.

  2. Я не пам'ятаю подробиць, але я чув у перші дні Java, що на кожний об’єкт Java існує mutex, який повинен бути придбаний та випущений кожним методом. Це, як правило, дозволяє краще адаптуватися до одночасності, хоча, на жаль, лише мютекс на об'єкт не захистить вас від перегонів або тупиків або будь-якого поганого, що може статися в паралельних програмах. Ця частина, якщо це правда, трохи наївна, але вона виходила з добрих намірів. Не соромтеся заповнити мені деталі, якщо ви знаєте більше про цей аспект.

  3. Інший спосіб, яким Java є мовою високого рівня, є створення сміття . Garbage-Collection може бути повільніше , ніж mallocта freeдля програм , які виділяють відразу всю пам'ять , вони повинні і працювати з цим. Проблема полягає в тому, що мовами, які не мають Garbage-Collection, програмісти, як правило, записують лише програми, які виділяють всю необхідну їм пам'ять відразу, і виходять з ладу, якщо виявиться, що якась довільна константа максимального розміру була перевершена. Тож порівняння - це яблука з апельсинами. Коли програмісти докладають зусиль для написання та налагодження програм з динамічним розподілом ланцюгових структур мовами, що не належать до GC, вони іноді виявляють, що їх програми вже не швидші, ніж на мові GC, оскількиmalloc іfreeне вільні! Вони також мають накладні витрати ... Плюс до цього, не маючи сил GC визначати, хто що вивільняє, а також, коли хтось звільняє, що в свою чергу, змушує вас робити копії - коли для кількох функцій потрібні дані, і не зрозуміло, яка буде використовувати його останнім - тоді як копіювання не було б необхідним мовою GC.


1. Мабуть, це неправда з HotSpot. 2. Тільки якщо ви позначите метод синхронізованим.
Вінстон Еверт

1
1. Компілятор не оптимізує код, але JVM досить розумний, щоб динамічно визначати лише один або два віртуальних методу, як правило, викликається і може викликати їх статично або навіть вбудовувати їх. Я впевнений, що C ++ не може вбудувати віртуальні методи. 2. Кожен об'єкт Java має блокування. Він має невеликі накладні витрати (приблизно в байт) на кожен об'єкт, але має незначний вплив, якщо не використовується. 3. У Java ви можете виділити відразу всі необхідні вам об'єкти. Це може дати вам додаток, який не GC цілий день. ;) GC Java неявно багатопотоковий, для чого потрібні спеціальні бібліотеки в C ++.
Пітер Лорі

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

2

У середині дев'яностих років, коли Java потрапила в мейнстрім, C ++ була домінуючою мовою, а Інтернет був ще досить новим. Також JVM та GC були відносно новими концепціями в розробці основних напрямків. Ранні JVM були настільки повільними (порівняно з C ++, що працюють на голому металі), а також часом страждали від довгих пауз з вивезенням сміття, що призвело до того, що репутація Java повільна.


це було пов'язано з технологією, що стоїть за ГК? Я знаю, що у них є деякі стратегії (наприклад, генераційні шари для об'єктів), щоб бути ефективнішими на фазі GC. Якою була стратегія на той час?
Стефано Борині

1
Експерт IANA JVM, але я думаю, на той час існував єдиний алгоритм розмітки / розгортки, використовуваний для GC, який вимагав, щоб весь JVM призупинявся під час виконання GC. На сьогоднішній день існує паралельна оцінка / розгортка, а також є багато інших поліпшень продуктивності в JVM.
Кен Лю

2
Сучасні алгоритми ГК приємні, але я думаю, що найбільшим вдосконаленням став JIT.
Паскаль Thivent

1

У багатьох додатках для настільних програм Java (таких випадків, як Eclipse) є погана реакція на графічний інтерфейс, можливо, це пов'язано з великим споживанням пам'яті та тим, що завантажувач класів може робити багато IO. Це покращується, але було гірше кілька років тому.

Багато (більшість) людей люблять робити узагальнення, тому вони кажуть "Java повільна", оскільки вони сприймають, що програми є повільними, коли вони взаємодіють з ними.


чи вважаєте ви, що велике споживання пам’яті відбувається за допомогою інструменту або з бібліотек Java?
Стефано Борині

У разі Eclipse - від самої інфраструктури Eclipse. Те саме для "важких" графічних інтерфейсів в минулому (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-компілятори можуть сильно використовувати час виконання поведінку та платформу, на якій вони працюють.


6
Я думаю , що ви мали в виду , щоб сказати, що JIT-компілюється (не тлумачиться) код буде бити АОТ код. Інтерпретація завжди буде повільнішою, ніж виконання компільованого коду. Саме тому використовуються компілятори JIT. Улов: між компілятором випереджаючого часу та компілятором JIT є невелика різниця в плані виводу, за винятком того, що компілятор JIT повинен компілюватись швидше, і він може використовувати інформацію про час роботи, щоб натякнути на його оптимізацію. Платформовані компілятори AoT з оптимізаціями для платформи майже завжди обіграють JIT, оскільки немає обмежень, скільки часу вони витрачають на оптимізацію.
BobMcGee

Дякуємо за відповідь, ніколи не замислюючись про те, що мало часу укладачів JIT є у їхньому розпорядженні.
helpermethod

Ви маєте на увазі щось на зразок адаптивної оптимізації точки доступу?
Стефано Борині

2
@BobMcGee: Дуже правильно. Програма C ++ може бути побудована для повільного запуску із зворотним зв’язком профілю для всіх її операцій. Тоді компілятор може відновити дуже швидку версію, використовуючи півгодини часу процесора та 2 ГБ оперативної пам’яті. JIT, який зробив це, змусив користувачів піти.
Zan Lynx

1
Час компіляції JIT незначний для тривалих програм, таких як сервери. AOT з PGO є більш обмеженим порівняно з JIT щонайменше з 2 причин. По-перше, найбільша різниця в продуктивності досягається легкими оптимізаціями. Порівняйте gcc -O2 з gcc -O3. Більшу частину часу різниці немає , іноді -O3 може бути трохи краще, іноді трохи гірше, але я ніколи не відчував різниці> 2 рази від цього. По-друге, використовуючи AOT навіть з PGO, ви можете лише здогадуватися, який профіль буде на сайті використання. Вгадайте неправильно, і ви далеко позаду СТІ. А власне профіль може бути надзвичайно конфігураційно-залежним.
Piotr Kołaczkowski
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.