Чому JIT не керує кодом JIT кеш?


107

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

Питання в тому, чому цей компільований код, кешований на диску, не використовується для подальшого використання тієї ж функції / класу?

Як відомо, щоразу, коли програма виконується, компілятор JIT запускається знову, а не використовуючи попередньо складену версію коду. Чи не додавання цієї функції не додасть суттєвого імпульсу початковому часу запуску програми, коли байт-код по суті інтерпретується?


4
Нитка обговорення цієї проблеми: javalobby.org/forums/thread.jspa?threadID=15812
Міку

2
Але навряд чи питання, яке приверне остаточну відповідь.
bmargulies

1
Я не впевнений у "значному" підвищенні, тому що тоді вам доведеться завантажувати JITted речі з диска, а не JITing його в пам'ять. Це може прискорити справи, але в кожному конкретному випадку.
Р. Мартіньо Фернандес

1
Дякую за чудові відповіді всім! Усі відповіді були однаково справедливі, тому я пішов із спільнотою на цю ...
Chinmay Kanchi,

Це гарне запитання, якщо ви запитаєте мене :)
Альфред

Відповіді:


25

Не вдаючись до cut'n'paste посилання, яке розмістив @MYYN, я підозрюю, що це тому, що оптимізації, які виконує JVM, не є статичними, а досить динамічними, заснованими на шаблонах даних, а також на кодових моделях. Ймовірно, що ці шаблони даних зміняться протягом життя програми, що зробить кешовані оптимізації менш оптимальними.

Тож вам знадобиться механізм, щоб встановити, чи були збережені оптимізації все ще оптимальними, і тоді ви можете просто повторно оптимізувати на ходу.


6
... або ви можете просто запропонувати наполегливість як варіант , як це робить JVM Oracle - розширення можливостей передових програмістів для оптимізації роботи програми, коли і де вони просто знають, що моделі не змінюються під їх відповідальність. Чому ні?!
Алекс Мартеллі

2
Бо це, мабуть, не варто. Якщо ані SUN, IBM, ані BEA не вважали це вартим для своїх JVM, то це буде вагомою причиною. Можливо, їх оптимізація RT швидша, ніж у Oracle, саме тому Oracle кешує її.
скафман

9
Чому б не взяти збережені оптимізації як вихідну точку, щоб використовувати те, що було вивчено на попередніх пробігах? З цього моменту JIT може працювати, як завжди, ре-оптимізувати речі. Після вимкнення цей код може зберігатися знову і використовуватись у наступному запуску як нова вихідна точка.
Пуче

1
@Puce Єдиною причиною, про яку я можу подумати, є те, що AFAIK не отримує статистики профілювання за допомогою оптимізованого коду. Тож у вас би не було способу покращитись ...
maaartinus

1
Я особисто був би в порядку з опцією "просто зберігати інформацію про профілювання JIT між прогонами" з усіма попередженнями про те, що "це буде дійсно лише з таким самим JVM, тими ж даними тощо та ігноруватися в іншому випадку". Що стосується того, чому це не було реалізовано, я би сподівався, що додаткова складність збереження та перевірки насіннєвих даних про JIT була занадто великою, щоб взяти ресурси з інших проектів. З огляду на вибір між цим та потоками Java 8 лямбда +, я б хотів мати останній.
Thorbjørn Ravn Andersen

25

JVM Oracle дійсно документально підтверджено для цього - цитуючи Oracle,

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

Я не знаю, чому всі складні реалізації VM не пропонують подібних варіантів.


8
Оскільки в інших витончених JVM немає придатних великих підприємств RDBMS, зручних для зберігання речей :)
skaffman

Оце Так! це означає, що компіляції кешуються часом. Це гарна новина!
Сандіп Джиндал

J9 IBM також документально підтверджено для цього.
користувач314104

9
Зауважте, що цей Oracle JVM - це всередині бази даних Oracle, а не завантажений Oracle при покупці Sun.
Thorbjørn Ravn Andersen

14

Оновлений до існуючих відповідей - Java 8 має JEP, призначений для вирішення цього питання:

=> JEP 145: Складений кеш-код . Нове посилання .

На дуже високому рівні його заявлена мета :

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

Сподіваюся, це допомагає.


3
Ця функція не дійшла до остаточного випуску .
assylias

5

Excelsior JET має кешируючий JIT-компілятор з версії 2.0, випущений ще в 2001 році. Більше того, його компілятор AOT може перекомпілювати кеш-пам'ять в один об'єкт DLL / спільний доступ, використовуючи всі оптимізації.


3
Так, але питання стосувалося канонічного JVM, тобто JVM Sun. Я добре знаю, що є кілька компіляторів AOT для Java, а також інші кешування JVM.
Chinmay Kanchi

0

Я не знаю справжніх причин, не беручи жодної участі у впровадженні СВМ, але я можу придумати деякі правдоподібні:

  • Ідея Java - це бути мовою, що записується коли-небудь, і введення попередньо складених матеріалів у файл класу є таким чином, що це порушує (лише "вид", оскільки, звичайно, фактичний байт-код все ще буде)
  • Це збільшило б розміри файлів класу, тому що ви мали б один і той же код там кілька разів, особливо якщо вам трапляється запускати одну і ту ж програму під декількома різними JVM (що насправді не рідкість, коли ви вважаєте різні версії різними JVM, які ви справді треба робити)
  • Файли класів самі по собі можуть бути недоступними для запису (хоча це було б досить легко перевірити)
  • Оптимізації JVM частково базуються на інформації про час виконання, а в інших програмах вони можуть бути непридатними (хоча вони все-таки повинні забезпечити певну користь)

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

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


1
У файлі класу є місце для таких речей, інфакт, який був оригінальним наміром (збережіть код JIT'ed як атрибут у класі файлу).
TofuBeer

@TofuBeer: Дякую за підтвердження. Я підозрював, що це може бути так (саме це я і зробив би), але не був впевнений. Відредаговано, щоб усунути це як можливу причину.
JaakkoK

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

1
Останній абзац про явний компілятор байт-коду до рідного - це те, що у вас є .NET з NGEN ( msdn.microsoft.com/en-us/library/6t9t5wcf(VS.71).aspx ).
Р. Мартіньо Фернандес
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.