Обновить
1

Independent Researcher & Developer

3
Подписчики
Отправить сообщение

@kmatveev,
Поделитесь своим опытом фиксирования пауз GC в GraalVM. Какие инструменты использовали? Какую проблему решали?

@kmatveev, я очень рад, что статья и комментарии смогли привлечь ваше внимание и зацепить.

@scherlock, @Siemargl, спасибо за дискуссию! Перечитывал и обдумывал с чего начать.

@scherlock,

Первое что стоит отметить, когда работаешь с 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).

Отметил себе раскрыть эти темы в будущих статьях.

С моей зарплатой в виде мерча (футболки и носков) из меня так себе продавец.
Если по существу: укажите, где именно в статье вы увидели претензию на авторство GraalVM?
Исследование как раз про разницу в производительности готовых решений Axiom JRE и Axiom NIK.
Всё указанное, что я проделал - вы можете успешно повторить. В репозитории лежат скрипты сборки контейнеров, которые собирают образы на базе бесплатных образов из Docker Hub.

@ris58h,
Я допустил ошибку в блоке. Спасибо за замечание!
Слышу критику. Меняюсь.
Вам и всем остальным неравнодушным +!

@pkokoshnikov, справедливо заметили, что важная часть работы Native Image в части CPU не была задокументирована.

Текущую статью дополнил материалами. Но это самый минимум в данной статье, который я смог сделать с тем материалом, который был собран.

В будущих работах уделю внимание производительности и показателям утилизации CPU, методике нагрузочного тестирования. Отметил себе.

@faxenoff, @pkokoshnikov, @broondulyak, спасибо за дискуссию!
Действительно, у Java изначальная философия была один раз код напиши и запускай на разных платформах.

В современных реалиях - собери один раз в контейнер, запускай контейнер.

Если речь про другой стек (например: JavaFX, Java Swing; где пользователи работают с окнами) и необходимо охватить пользователей разных ОС, то здесь Native Image действительно понадобиться собирать под каждую ОС отдельно.

Вообще, есть смысл в новых работах уделить внимание CI/CD. Пометил себе.

@Dhwtj, всё верно! Справедливо указали "налог на сборку" и возможную просадку производительности в сравнении с прогретым JIT!

В следующих работах постараюсь включить исследования, связанные с PGO (Profile-Guided Optimization) и использование современных версий GraalVM. PGO позволит догнать производительность с 80% (в среднем при компиляции) до 100% (на 10-20%), а современные версии GraalVM должны компилировать код гораздо быстрее.

Дополню, что помимо микросервисов, самые идеальные задачи для GraalVM - это задачи, когда нужно запустить приложение, выполнить приложение, завершить приложение (консольные утилиты, утилиты с графическим интерфейсом).

@kmatveev, справедливое замечание по поводу дискретности мониторинга!

Действительно, Prometheus/Grafana с дефолтным шагом скрейпинга может не увидеть паузы в 1-5 мс.

В новых сравнениях/работах добавлю анализ работы через JFR и прямой профайлинг GC logs. Должны буду видны микро паузы, которые спрятались.

@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-режим.
Постараюсь подготовить материалы на эту тему.

@ruslan_astratov спасибо за обратную связь!
Какие варианты оптимизации открыли для себя?
Удалось применить их в деле?

@alexander_pesh , @Pdasilem , @Siemargl , @GreyN , спасибо за дискуссию!

В данной статье была цель предоставить варианты оптимизации кода, в том числе и Правило №7. BigDecimal vs Long (Битва за примитивы).

Действительно, если проект находится на этапе реализации, то смело используйте BigDecimal. Выше указали основные аргументы почему стоит использовать BigDecimal и какие вопросы он решает + накину свои:

  • Проблема деления (Scale Up)

  • Проблема переполнения (Overflow)

  • Сложность поддержки. Необходим дополнительный контроль в большой команде с разной экспертизой. Банальная проблема - есть риск забыть привести данные к нужному формату

  • Стандартное бизнес-приложение, много операций делений/процентов

По результатам нагрузочного тестирования можно будет сформировать понимание - необходимо ли производить оптимизации.

Когда стоит сразу задуматься об использовании денежных значений в минимальных единицах (long / int):

  • High-load

  • Критичен бюджет аллокаций (жёсткий лимит ресурсов)

  • Пишите ядро торгового движка/блокчейна

@remindscope отличная точка для дискуссии!
Если вопрос в написании нового решения в 2026 году, есть эксперты в команде по Go - почему бы и не написать на языке Go? Да конечно можно!
И с философией Java так же правы - пиши один код и запускай везде!

GraalVM - это не сова, это вынужденная адаптация Java под современные реалии облаков (Cloud Native). В данном случае Java просто эволюционирует, чтобы не проиграть Go или Rust в нише маленьких контейнеров. При этом концепция запуска бинарника под каждую платформу также сохраняется, но с некоторой "эволюцией" - запуск внутри контейнера.

Контейнеризация заставляет и главное, что позволяет большинству технологий прогрессировать и меняться в лучшую сторону.

@yrub, снимаю шляпу! Про SSA-форму - в точку!
Внёс уточнение в статью, чтобы не плодить мифы.

Информация

В рейтинге
Не участвует
Зарегистрирован
Активность