а. Як сьогодні швидкість Java порівнюється з C ++?
Важко виміряти. Варто зазначити, що основна частина швидкості впровадження, це розподільник пам'яті, є дуже різними алгоритмами в Java та C ++. Недетермінований характер колектора ускладнює отримання значущих даних про продуктивність порівняно з детермінованим управлінням пам'яттю C ++, тому що ви ніколи не можете бути впевнені, у якому стані знаходиться колектор. Це означає, що дуже важко написати еталон що може означати їх порівняння. Деякі шаблони розподілу пам'яті працюють набагато швидше за допомогою GC, деякі - набагато швидше за допомогою нативного розподільника.
Однак я б сказав, що Java GC повинен працювати швидко в будь-якій ситуації. Народний розподільник, однак, можна замінити на той, який є більш підходящим. Нещодавно я поставив запитання на тему SO, чому C # Dictionary
може виконати (0,45 мс на моїй машині) порівняно з еквівалентомstd::unordered_map
який виконується на (10 мс на моїй машині). Однак, просто замінивши розподільник і хешер на більш відповідні, я скоротив цей час виконання до 0,34 мс на моїй машині - тридцяту частину початкового часу роботи. Ви ніколи не могли сподіватися виконати таку спеціальну оптимізацію за допомогою Java. Прекрасним прикладом, де це може по-справжньому змінити, є нарізка різьби. Бібліотеки власних потоків, такі як TBB, забезпечують кешування потоків алокаторів, які значно швидше, ніж традиційні алокатори, при роботі з багатьма виділеннями на багатьох потоках.
Зараз багато людей будуть говорити про вдосконалення JIT та про те, як про JIT є більше інформації. Звичайно, це правда. Але це навіть далеко не близьке до того, що може підключити компілятор C ++ - тому що компілятор має, порівняно, нескінченний час і простір, в якому можна запустити, з точки зору часу виконання остаточної програми. Кожен цикл і кожен байт, який JIT витрачає на роздуми про те, як найкраще оптимізувати свою програму, - це цикл, який ваша програма не витрачає на виконання та не може використовувати для власних потреб в пам'яті.
Крім того, завжди знайдуться випадки, коли компіляція та JIT-оптимізація не зможуть довести певних оптимізацій, особливо у випадку таких речей, як аналіз втечі. У C ++, то в якості значення в стеку в будь-якому випадку , компілятор не повинен виконувати його. Крім того, є прості речі, як-от суцільна пам'ять. Якщо ви виділите масив на C ++, то ви виділите єдиний суміжний масив. Якщо ви виділите масив у Java, то він зовсім не суміжний, оскільки масив заповнений лише покажчиками, які могли вказувати куди завгодно. Це не тільки обсяг пам'яті та час на подвійні непрямі, але й кеш-накладні витрати. Така річ - це те, коли мовна семантика Java просто нав'язує, що вона повинна бути повільнішою, ніж еквівалентний код C ++.
Зрештою, мій особистий досвід полягає в тому, що Java в середньому може становити приблизно половину швидкості С ++. Однак реально немає можливості створити резервні копії будь-яких заяв про ефективність без надзвичайно всебічного набору орієнтирів через принципово різних алгоритмів.
б. Чи можна було б створити сучасний заголовок AAA за допомогою Java?
Я припускаю, що тут ви маєте на увазі "гру", а не шанс. По-перше, вам доведеться писати все з нуля, як майже всі існуючі бібліотеки та цільову інфраструктуру C ++. Хоча це не робить неможливе саме по собі, воно, безумовно, може внести вагомий внесок у нездійсненне. По-друге, навіть двигуни C ++ навряд чи можуть вписатися в крихітні обмеження пам’яті існуючих консолей - якщо JVM навіть існують для цих консолей, - а гравці ПК очікують трохи більше на їх пам’ять. Створення ефективних ігор AAA досить складно в C ++, я не бачу, як цього можна досягти в Java. Ніхто ніколи не писав гру AAA зі значним часом, проведеним мовою, що не складається. Більше того, це було б просто дуже схильне до помилок. Детерміновані знищення є важливими при роботі, наприклад, з ресурсами графічного процесора - і на Java, ви '
c. У яких областях Java повільніше, ніж C ++, якщо вона взагалі? (тобто розбивка чисел, графіка або просто все навколо)
Я б точно пішов на багатоборство. Принципово-посилальний характер усіх об'єктів Java означає, що у Java набагато більше непрямих та посилань у ній, ніж у C ++ - приклад, який я наводив раніше з масивами, але також стосується, наприклад, усіх об'єктів-членів. Якщо компілятор C ++ може шукати змінну члена за постійний час, час виконання Java повинен слідувати за іншим вказівником. Чим більше ви будете отримувати доступ, тим повільніше це станеться, і JIT нічого з цим не може зробити.
Якщо C ++ може звільнити та знову використати частину пам'яті майже миттєво, у Java вам доведеться чекати колекції, і я сподіваюся, що цей фрагмент не вийшов із кешу, і, по суті, потрібна більше пам'яті, означає менший кеш-пам'ять та ефективність підкачки. Потім подивіться на семантику таких речей, як бокс та розпакування. У Java, якщо ви хочете посилатися на інт, вам доведеться динамічно розподіляти його. Це властивий відхід порівняно з семантикою С ++.
Тоді у вас є проблема з дженериками. На Java ви можете оперувати загальними об'єктами лише завдяки успадкуванню часу виконання. У C ++ шаблони мають буквально нульові накладні витрати - щось не може відповідати Java. Це означає, що весь загальний код на Java за своєю суттю повільніше, ніж загальний еквівалент у C ++.
І тоді ви приходите до Невизначеної поведінки. Усі ненавидять його, коли їх програма виставляє UB, і всі хочуть, щоб її не існувало. Однак UB принципово дозволяє оптимізувати, які ніколи не можуть існувати на Java. Погляньте на цю публікацію, що описує оптимізацію на основі UB. Невизначення поведінки означає, що реалізація може зробити більше оптимізацій та зменшити код, необхідний для перевірки на умови, які не визначені в C ++, але визначені в Java.
Принципово семантика Java диктує, що мова йде повільніше, ніж C ++.
Чи вважається Java тепер складеною мовою чи інтерпретованою мовою?
Він насправді не вписується ні в одну з цих груп. Я б сказав, що кероване - це справді окрема категорія, хоча я б сказав, що це, безумовно, більше схожа на інтерпретовану мову, ніж на компільовану мову. Що ще важливіше, існує майже дві основні керовані системи, JVM та CLR, і коли ви говорите "керовані", це досить чітко.
Які основні недоліки Java, які були усунені з перших днів?
Автоматичний бокс та розпакування - це єдине, що я знаю. Дженрік вирішує деякі питання, але далеко не багато.
Які основні недоліки Java ще не вирішено?
Їх дженерики дуже-дуже слабкі. Загальна інформація про C # є значно сильнішою, хоча, звичайно, не є досить шаблонами. Детерміновані руйнування - ще одна значна нестача. Будь-яка форма лямбда / закриття також є головною проблемою - ви можете забути функціональний API на Java. І, звичайно, завжди є питання ефективності, для тих напрямків, які їм потрібні.