Проект Java Valhalla

1. Огляд

У цій статті ми розглянемо проект Valhalla - історичні причини його виникнення, поточний стан розробки та те, що він представляє для повсякденного розробника Java після його випуску.

2. Мотивація та причини проекту «Вальхалла»

В одній зі своїх доповідей Брайан Гетц, архітектор мови Java в Oracle, зазначив, що однією з головних мотивацій проекту Valhalla є бажання адаптувати мову Java та середовище виконання до сучасного обладнання . Коли була задумана мова Java (приблизно 25 років тому на момент написання статті), вартість отримання пам'яті та арифметичної операції була приблизно однаковою.

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

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

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

3. Типи цінностей

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

Оскільки у нас більше немає ідентичності об’єкта, ми можемо відмовитись від покажчиків і змінити загальний макет пам’яті типів значень порівняно з об’єктом. Давайте розглянемо порівняння розміщення пам’яті між класом Point та відповідним типом значення Point.

Код і відповідне розташування пам'яті звичайного класу Point буде:

final class Point { final int x; final int y; }

З іншого боку, код і відповідний макет пам'яті типу значення Point має бути:

value class Point { int x; int y }

Це дозволяє JVM згладжувати типи значень на масиви та об'єкти, а також на інші типи значень. На наступній діаграмі ми представляємо негативний ефект опосередкованості, коли ми використовуємо клас Point у масиві:

З іншого боку, тут ми бачимо відповідну структуру пам’яті типу значення Point [] :

Це також дозволяє JVM передавати типи значень у стек, замість того, щоб розподіляти їх у купі. Врешті-решт, це означає, що ми отримуємо агрегати даних, які мають поведінку під час виконання, подібну до примітивів Java, наприклад int або float .

Але на відміну від примітивів, типи значень можуть мати методи і поля. Ми також можемо реалізувати інтерфейси та використовувати їх як загальні типи. Тож ми можемо поглянути на типи значень з двох різних сторін:

  • Швидші об'єкти
  • Визначені користувачем примітиви

Як додаткову глазур на торті ми можемо використовувати типи цінностей як загальні типи без боксу. Це безпосередньо веде нас до іншої великої особливості проекту Valhalla: спеціалізованих дженериків.

4. Спеціалізовані дженерики

Коли ми хочемо згенерувати над мовними примітивами, ми в даний час використовуємо типи в коробці, такі як Integer для int або Float для float . Цей бокс створює додатковий рівень опосередкованості, тим самим перемагаючи мету використання примітивів для підвищення продуктивності.

Тому ми бачимо багато спеціалізованих спеціалізацій для примітивних типів у існуючих фреймворках та бібліотеках, таких як IntStream або ToIntFunction . Це робиться для підвищення ефективності використання примітивів.

Отже, спеціалізовані дженерики - це спроба усунути потреби у цих "хаках". Натомість мова Java прагне увімкнути загальні типи практично для всього: посилання на об’єкти, примітиви, типи значень і, можливо, навіть недійсні .

5. Висновок

Ми поглянули на зміни, які проект Valhalla внесе в мову Java. Дві основні цілі - це підвищення ефективності та менш діряві абстракції.

Покращення продуктивності вирішується шляхом згладжування графіків об’єктів та усунення побічних ефектів. Це призводить до більш ефективних компонувань пам'яті та меншої кількості виділень та збирання сміття.

Краща абстракція поставляється з примітивами та об’єктами, які мають більш подібну поведінку, коли використовуються як загальні типи.

Ранній прототип проекту Valhalla, який впроваджує типи значень в існуючу систему типів, має кодову назву LW1.

Ми можемо знайти більше інформації про проект Valhalla на відповідній сторінці проекту та JEP:

  • Проект Valhalla
  • JEP 169: Цінні об'єкти
  • JEP 218: Дженерики над примітивними типами