Привет!
У меня в новом сервисе в Проекте Э на Spring Boot 3.5 новый рекорд скорости тестов:)
54 кейса за 2.7 секунды, 90% тестов - < 60мс, медиана - 14мс.
Сетап:
1. инфра (PostgreSQL и Minio на RAM-диске) запускается руками по кнопке в Идее docker compose-ом.
2. Отказ от компонент скана бинов
3. Отказ от скана авто-конфигов
4. ленивая иницилазиация бинов (spring.main.lazy-initialization)
5. Работа через WebTestClient с MockMvc
Не 5мс на кейс, как у Саши Раковского, конечно, но уже близко и это полный набор тестов, после которого можно деплоить в прод:)
#ergo_testing@ergonomic_code #project_e@ergonomic_code #spring_boot@ergonomic_code
У меня в новом сервисе в Проекте Э на Spring Boot 3.5 новый рекорд скорости тестов:)
54 кейса за 2.7 секунды, 90% тестов - < 60мс, медиана - 14мс.
Сетап:
1. инфра (PostgreSQL и Minio на RAM-диске) запускается руками по кнопке в Идее docker compose-ом.
2. Отказ от компонент скана бинов
3. Отказ от скана авто-конфигов
4. ленивая иницилазиация бинов (spring.main.lazy-initialization)
5. Работа через WebTestClient с MockMvc
Не 5мс на кейс, как у Саши Раковского, конечно, но уже близко и это полный набор тестов, после которого можно деплоить в прод:)
#ergo_testing@ergonomic_code #project_e@ergonomic_code #spring_boot@ergonomic_code
🔥8👍7
Привет!
Обещанный микропост про эксперимент с http4k.
Напомню контекст - мне недавно понадобилось сделать в Проекте Э новый небольшой сервис и у нас довольно сильно ограничена RAM на стендах, поэтому я решил поэксперементировать с http4k +jooq jdbi с целью сократить потреблением RAM.
Изначально я написал прототип на Spring Boot 3.5 (MVC + Data JDBC) буквально с парой методов - создание сущности на 3 поля плюс файла (в минио) и получение файла.
Далее методика всех измерений была следующая:
1. запустить сервис
2. curl-запросами создать сущность и получить картинку
3. померить ps-ом RSS процесса.
И для чистого Spring Boot я получил 270mb.
Тогда я написал прототип на http4k + jdbi и для него получил 236mb. В целом на этом можно было бы и закончить эксперимент, т.к. экономия была несущественная, зато с http4k пришлось бы руками писать аутентификацию, rbac, управление транзакциями, кэширование, да ещё и запросы на доменные модели руками мапить.
Но я не закончил и накопал ещё пару любопытных штук.
Первым делом я пошёл к гопатычу и спросил какой стэк под JVM дал бы большую экономию по памяти. Он накидал несколько вариантов, среди которых обещал ~150mb RAM для Micronaut. Я спросил за счёт чего Micronaut экономит память. Он сказал - за счёт Netty.
Я думаю ну ладно, в http4k переехать на Netty - дело пары строк.
И переехал. И получил 156mb RAM.
А заодно ещё и дикий WTF - у http4k API обработчиков запросов - синхронное. И нет ручки, чтобы настроить Netty на виртуальные потоки. То есть из коробки Netty в http4k - это фикция.
Пока разбирался как таки примострячить виртуальные потоки в http4k/Netty залез в исходники и нашёл там коммент с "элегантым" решением этой проблемы:
Ну т.е. хотите чтобы Нетти норм работал - копипастьте код либы и делайте с ним что хотите🤦♂️ О каких 99% юзкейсах они говорят - вообще не представляю.
В общем поматерился я на хттп4к и подумал, что Spring Boot же тоже может в Netty. И там вроде как даже не обязательно делать контроллеры на Reactor-е или корутинах - вроде как можно писать обычные контроллеры и настроить (вот это ничего себе!) тредпул на котором Спринг будет их дёргать.
Сказано-сделано, минут за 15-30 переехал на WebFlux, барабанная дробь... 245mb... Тут у меня бюджет на эксперименты начал уже заканчиваться, поэтому я решил, что дело количества зависимостей, которые тащит с собой WebFlux и пошёл дальше.
А дальше я решил дать ещё один шанс Spring Boot Native. Как и в прошлый раз пришлось повоевать с рефлекшеном, но на этот раз со мной был GPT-5 и эти проблемы он щёлкал на раз-два, поэтому ещё минут через 30 я получил цифры для нативной сборки - 157mb. Неплохо.
Однако пока копался с Нативом, я наткнулся на Spring Boot Ahead-of-Time Processing, который должен был дать оптимизацию времени запуска и потребления RAM без 3 минут компиляции и сюрпризов в рантайме Нативной сборки. И он в целом дал - 234mb RAM.
Итого вышли такие цифры:
1. Spring Boot + Tomcat - 270mb
2. http4k + Jetty - 236mb
3. http4k + Netty - 156mb
4. Spring Boot + Netty - 245mb
3. Spring Boot Native + Tomcat - 157mb
4. Spring Boot AOT Processing + Tomcat - 234mb
Помедитировав на них я решил, что переход на http4k того не стоит и снова остался на Spring Boot. Не люблю его за монструозность и количество автомагии но для меня сейчас он всё ещё остаётся наименьшим из зол.
#spring_boot@ergonomic_code #project_e@ergonomic_code
Обещанный микропост про эксперимент с http4k.
Напомню контекст - мне недавно понадобилось сделать в Проекте Э новый небольшой сервис и у нас довольно сильно ограничена RAM на стендах, поэтому я решил поэксперементировать с http4k +
Изначально я написал прототип на Spring Boot 3.5 (MVC + Data JDBC) буквально с парой методов - создание сущности на 3 поля плюс файла (в минио) и получение файла.
Далее методика всех измерений была следующая:
1. запустить сервис
2. curl-запросами создать сущность и получить картинку
3. померить ps-ом RSS процесса.
И для чистого Spring Boot я получил 270mb.
Тогда я написал прототип на http4k + jdbi и для него получил 236mb. В целом на этом можно было бы и закончить эксперимент, т.к. экономия была несущественная, зато с http4k пришлось бы руками писать аутентификацию, rbac, управление транзакциями, кэширование, да ещё и запросы на доменные модели руками мапить.
Но я не закончил и накопал ещё пару любопытных штук.
Первым делом я пошёл к гопатычу и спросил какой стэк под JVM дал бы большую экономию по памяти. Он накидал несколько вариантов, среди которых обещал ~150mb RAM для Micronaut. Я спросил за счёт чего Micronaut экономит память. Он сказал - за счёт Netty.
Я думаю ну ладно, в http4k переехать на Netty - дело пары строк.
И переехал. И получил 156mb RAM.
А заодно ещё и дикий WTF - у http4k API обработчиков запросов - синхронное. И нет ручки, чтобы настроить Netty на виртуальные потоки. То есть из коробки Netty в http4k - это фикция.
Пока разбирался как таки примострячить виртуальные потоки в http4k/Netty залез в исходники и нашёл там коммент с "элегантым" решением этой проблемы:
Stock version of an Netty Server. Not that if you want to configure your own server instance you
can duplicate this code and modify it as required. We are purposefully trying to limit options
here to keep the API simple for the 99% of use-cases.
Ну т.е. хотите чтобы Нетти норм работал - копипастьте код либы и делайте с ним что хотите
В общем поматерился я на хттп4к и подумал, что Spring Boot же тоже может в Netty. И там вроде как даже не обязательно делать контроллеры на Reactor-е или корутинах - вроде как можно писать обычные контроллеры и настроить (вот это ничего себе!) тредпул на котором Спринг будет их дёргать.
Сказано-сделано, минут за 15-30 переехал на WebFlux, барабанная дробь... 245mb... Тут у меня бюджет на эксперименты начал уже заканчиваться, поэтому я решил, что дело количества зависимостей, которые тащит с собой WebFlux и пошёл дальше.
А дальше я решил дать ещё один шанс Spring Boot Native. Как и в прошлый раз пришлось повоевать с рефлекшеном, но на этот раз со мной был GPT-5 и эти проблемы он щёлкал на раз-два, поэтому ещё минут через 30 я получил цифры для нативной сборки - 157mb. Неплохо.
Однако пока копался с Нативом, я наткнулся на Spring Boot Ahead-of-Time Processing, который должен был дать оптимизацию времени запуска и потребления RAM без 3 минут компиляции и сюрпризов в рантайме Нативной сборки. И он в целом дал - 234mb RAM.
Итого вышли такие цифры:
1. Spring Boot + Tomcat - 270mb
2. http4k + Jetty - 236mb
3. http4k + Netty - 156mb
4. Spring Boot + Netty - 245mb
3. Spring Boot Native + Tomcat - 157mb
4. Spring Boot AOT Processing + Tomcat - 234mb
Помедитировав на них я решил, что переход на http4k того не стоит и снова остался на Spring Boot. Не люблю его за монструозность и количество автомагии но для меня сейчас он всё ещё остаётся наименьшим из зол.
#spring_boot@ergonomic_code #project_e@ergonomic_code
Please open Telegram to view this post
VIEW IN TELEGRAM
👏8👍6🔥5❤3