Комментарии 31
Во всех нейтив сборках половина фичей Джавы не работает, а код исполняется медленнее. Не думаю что в этот раз что-то изменилось.
компилятор должен знать все пути исполнения при сборке. Поэтому рефлексия, JNI, динамические прокси и подгрузка классов на лету без явного описания в конфигах падают. Многие старые библиотеки не заводятся в принципе.
На практике в Spring Boot 3 и Quarkus это уже решено автоматической генерацией метаданных при сборке.
Все как обычно.
Генерация при сборке далеко не везде и не во всех случаях работает.
@BugM, @Dhwtj, спасибо за глубокие замечания!
Согласен, "Детские болезни" Native Image с рефлексией и JNI в эпоху Spring Boot 2 часто превращали разработку в квест по написанию конфигов.
А вообще, здесь напрашивается детальный разбор: Spring Boot 2 vs Spring Boot 3 (+ зацепить Spring Boot 4) в Native-режиме, как встроенный AOT-движок в SB3 (+SB4) реально решает проблемы с метаданными, сравнение производительности так же JVM VS Native-режим.
Постараюсь подготовить материалы на эту тему.
В Axiom NIK по умолчанию трудится Serial GC, и он делает это настолько филигранно, что система мониторинга просто не фиксирует пауз
может просто не умеет фиксировать паузы?
@kmatveev, справедливое замечание по поводу дискретности мониторинга!
Действительно, Prometheus/Grafana с дефолтным шагом скрейпинга может не увидеть паузы в 1-5 мс.
В новых сравнениях/работах добавлю анализ работы через JFR и прямой профайлинг GC logs. Должны буду видны микро паузы, которые спрятались.
Нейростатья, нейроответы в комментариях.
@kmatveev, я очень рад, что статья и комментарии смогли привлечь ваше внимание и зацепить.
@kmatveev,
Поделитесь своим опытом фиксирования пауз GC в GraalVM. Какие инструменты использовали? Какую проблему решали?
за старт в 1.4 с мы платим 13 минутами сборки
Также, очевидно, упала скорость по сравнению с jit после прогрева.
GraalVM для микросервисов. Для монолита jit
@Dhwtj, всё верно! Справедливо указали "налог на сборку" и возможную просадку производительности в сравнении с прогретым JIT!
В следующих работах постараюсь включить исследования, связанные с PGO (Profile-Guided Optimization) и использование современных версий GraalVM. PGO позволит догнать производительность с 80% (в среднем при компиляции) до 100% (на 10-20%), а современные версии GraalVM должны компилировать код гораздо быстрее.
Дополню, что помимо микросервисов, самые идеальные задачи для GraalVM - это задачи, когда нужно запустить приложение, выполнить приложение, завершить приложение (консольные утилиты, утилиты с графическим интерфейсом).
в 2000 году я запускал java на машине с процессором 80386 5Мб RAM под Win95. помню JRE что то около 1.8Мб в архиве был
И запускался дольше чем хостовая ОС.
Причем такое поведение наблюдалось еще много лет.
Только я под OS/2 Warp крутил. И позже под Netware 6
Все так. Но проблема сейчас в программистах после курсов и применении AI-генерации кода. Мой старый комп при прохождении вышеупомянутых курсов,к сожалению,сломался. Было обидно. Поэтому поднял тему оптимизаций Java-рантайма. Компьютеры нынче дорогие
"Мы сделали кроссплатформеное решение, которое надо компилировать под каждую платформу отдельно"
Никто не запрещает сделать просто отдельный пайплайн с найтив сборкой для деплоя в прод. Если нужно кроссплатформенное решение просто не делайте native образ. Код от этого не поменяется
кто сейчас запускает сервисы на "платформах"? образ собрал и отдал - все 🤷♂️
@faxenoff, @pkokoshnikov, @broondulyak, спасибо за дискуссию!
Действительно, у Java изначальная философия была один раз код напиши и запускай на разных платформах.
В современных реалиях - собери один раз в контейнер, запускай контейнер.
Если речь про другой стек (например: JavaFX, Java Swing; где пользователи работают с окнами) и необходимо охватить пользователей разных ОС, то здесь Native Image действительно понадобиться собирать под каждую ОС отдельно.
Вообще, есть смысл в новых работах уделить внимание CI/CD. Пометил себе.
Почему то нигде нет графиков сравнения утилизации cpu. У меня под нагрузкой сервис 10k rps. Реквесты 30 ядер лимиты 60. Достаточно много вычислений под капотом не просто crud. Почему такой важный параметр обошли стороной?
@pkokoshnikov, справедливо заметили, что важная часть работы Native Image в части CPU не была задокументирована.
Текущую статью дополнил материалами. Но это самый минимум в данной статье, который я смог сделать с тем материалом, который был собран.
В будущих работах уделю внимание производительности и показателям утилизации CPU, методике нагрузочного тестирования. Отметил себе.
У вас пункты дублируются начиная с 8го.
Я не буду отвечать в комментариях
И за это тоже минус.
@ris58h,
Я допустил ошибку в блоке. Спасибо за замечание!
Слышу критику. Меняюсь.
Вам и всем остальным неравнодушным +!
Опять продавцы из аксиом впаривают GraalVm как якобы "свое новейшее изобретение", которым оно никогда не являлось, за большие деньги между прочим
С моей зарплатой в виде мерча (футболки и носков) из меня так себе продавец.
Если по существу: укажите, где именно в статье вы увидели претензию на авторство GraalVM?
Исследование как раз про разницу в производительности готовых решений Axiom JRE и Axiom NIK.
Всё указанное, что я проделал - вы можете успешно повторить. В репозитории лежат скрипты сборки контейнеров, которые собирают образы на базе бесплатных образов из Docker Hub.
Вот что высокие цены на оперативку творят!
9.Парадок нагрузки
Хабр утонул в низкокачественных нейрогаллюцинациях, которые авторы даже не читают перед публикацией.
В случае с нативной сборкой цикл доставки сильно увеличивается(только не нужно мне рассказывать про то, что можно разные степени оптимизации нативного образа указывать).
Нативные сборки безусловно имеют свое место и нишу, но точно ни как мэйнстрим на сеголняшний день.
Для большей части приложений потребление памяти НЕ является проблемой.
На мой взгляд, революцией в Java станет внедрение Project Valhalla когда(если) его наконец доделают и внедрят.
Для большей части приложений потребление памяти НЕ является проблемой.
Уже давно ни одного Джава - приложения на компе. Нет Джавы - нет проблем с потреблением памяти.
А вообще конечно брейкинг ньюс - скомпилированные в нейтив приложения быстрее и меньше жрут. Но джаве даже АОТ не поможет - слишком много завязано на хип.
@scherlock, @Siemargl, спасибо за дискуссию! Перечитывал и обдумывал с чего начать.
Первое что стоит отметить, когда работаешь с Native Image цикл доставки меняется. У нас есть код в хранилище (repository) и следующий результат - контейнер с запечённым бинарником в Системе Артефактов. Внутрь бинарника уже не залезть (плюс векторы атак меньше на бинарник). Поэтому часть проверок (SAST и т.д.) должны уехать на коммиты/PR, а это в свою очередь распараллеливание процессов. И уже по факту надо будет смотреть, что с показателем TTM произойдёт.
Наверно, потребление памяти действительно не проблема, если стоимость оборудования оплачивается не из личного кармана, а из чужого. Если у бизнеса есть возможность оплачивать железо, требования к сервису позволяют использовать медленный старт приложения, latency больше нескольких секунд - да с лёгкостью можно отказаться от Native.
А вот с Project Valhalla нужно очень чётко понимать разницу с Native:
это разные уровни. Когда мы говорим про Native Image (GraalVM), то мы говорим об инфраструктурном уровне, который борется с оверхедом самой платформы (JVM). Project Valhalla - это архитектурный уровень, который борется с оверхедом модели данных.
Никто не запрещает использовать одновременно Native Image и Project Valhalla. Более того, они будут давать следующий эволюционный скачок в развитии Java.
@Siemargl,
Тут важно не путать процесс и результат.
AOT - это компилятор, способ сборки. У него задача - запечь код. У него работа закончилась, когда он собрал бинарник. Native Image - это бинарник. При работе бинарника динамическая компиляция кода не происходит.
Более того, появляется эффект при работе с памятью - меньше фрагментация и данные более скомпоновано лежат (Data Locality), что в свою очередь уже как раз даёт эффект при работе с данными (Data Prefetching).
Отметил себе раскрыть эти темы в будущих статьях.

Java на диете: 45 МБ RAM и старт за 1.4 с. Смертный приговор классическим JVM?