(java || kotlin) && devOps
355 subscribers
7 photos
1 video
7 files
354 links
Полезное про Java и Kotlin - фреймворки, паттерны, тесты, тонкости JVM. Немного архитектуры. И DevOps, куда без него
Download Telegram
Продолжение поста про расширения PostgreSQL.

Все что не влезло в предыдущий)

8) citext - case-insensitive хранение, а скорее сравнение строк в БД.

Создание таблицы с case-insensitive столбцом и вставка данных:

CREATE TABLE users (user_id SERIAL PRIMARY KEY, username CITEXT, email CITEXT);
INSERT INTO users (username, email) VALUES ('Иван Смирнов', 'ivan.smironoff@mail.ru');


Поиск без учета регистра:

SELECT * FROM users WHERE username = 'иван смирнов';


9) pg_stat_kcache - еще больше статистики по выполнению запросов, в особенности про работу с файловой системой - например, чтение из кэша ОС vs чтение с диска.
Что за данные собираются - можно узнать тут https://github.com/powa-team/pg_stat_kcache

Пример запроса: 5 самых затратных по времени запросов, их частоту выполнения, объемы обращений к диску и оперативной памяти, а также количество переключений контекста ядра ОС.

SELECT
round(total_exec_time::numeric, 0) AS time,
calls,
pg_size_pretty(exec_minflts * 4096) AS reclaim, pg_size_pretty(exec_majflts * 4096) AS faults,
pg_size_pretty(exec_reads) AS reads, pg_size_pretty(exec_writes) AS writes,
round(exec_user_time::numeric, 2) AS user_time, round(exec_system_time::numeric, 2) AS sys_time,
exec_nvcsws AS virtual_switches, exec_nivcsws AS involuntary_switches,
LEFT(query, 27) AS query_text
FROM pg_stat_statements s
JOIN pg_stat_kcache() k
USING(userid, dbid, queryid)
ORDER BY total_exec_time DESC
LIMIT 5;


10) isn - добавляет новые типы данных для проверки разного рода штрих кодов EAN13, UPC, ISBN (books), ISMN (music), and ISSN (serials) на допустимые префиксы. У модуля есть минус - набор допустимых префиксов постоянном меняется, следовательно, надо поддерживать актуальность расширения и может быть гэп по времени по поступлению обновлений.

Создание и вставка данных в таблицу с ISBN столбцом (уникальный номер книги):

CREATE TABLE test (id isbn);
INSERT INTO test VALUES('9780393040029');


11) pg_hint_plan - позволяет "прибить гвоздями" кусок плана выполнения запроса

Тут мы указываем, что надо использовать HashJoin и сразу смотрим реальный план выполнения запроса:

/*+ HashJoin(pt st) */
EXPLAIN SELECT * FROM s1.t1 st
JOIN public.t1 pt ON (st.id=pt.id);


12) pg_cron - что делает - понятно. Можно подумать, что расширение нарушает принцип - никакой логики в БД. Но оно полезно для другого - для служебных задач, например, периодически делать VACUUM:

SELECT cron.schedule('59 23 * * *', 'VACUUM');


На цифре 12 пожалуй и остановлюсь.

Что еще важно.
Часть расширений уже входит в поставку.
Какие именно - можно узнать выполнив команду:

SELECT * FROM pg_available_extensions;


Набор может различаться, в официальном дистрибутиве их на данный момент 60, в PostgrePro - 48, Сбер Pangolin - 119.

#postgresql #db #plugins
Астрологи объявили 2025 годом уязвимостей в Tomcat)

По крайней мере у меня складывается такое впечатление.
И похоже не только впечатление.
https://www.cve.org/CVERecord/SearchResults?query=apache+tomcat
24 уязвимости в 2025 году, по сравнению 15 с 2024. И год еще не закончился)

Предположу, что проблема скорее не в том, что Tomcat кривой по архитектуре или дырявый, а это обратная сторона популярности. Все-таки Tomcat - вариант по умолчанию встроенного сервера для Spring Boot приложений. И большинство его не меняют. Больше инсталляций, больше людей, которые их хотят сломать.

Но не Tomcat единым, как говорится.
Есть еще как минимум 4 сервера для JVM приложений:
1) Jetty
2) Undertow
3) Netty
4) Open Liberty

Все они production ready.
Кто может заменить Tomcat для Spring Boot приложений?
И нужно ли менять?

Начнем с того, кто не сможет.
Netty - это не контейнер сервлетов, синхронное взаимодействие Spring Web MVC он просто не поддерживает. Зато это выбор номер один для реактивщины. Как в Spring, так и в конкурирующих фреймворках Quarkus/Micronaut/Vert.x/Helidon.
И очевидно он выдает намного большую производительность и меньшее потребление памяти, по сравнению с Tomcat. Но требует полного переписывания логики на принципах реактивного программирования. А это сложно и требует я бы сказал повышенной квалификации.

Open Liberty - бывший IBM Websphere Liberty Profile, ушедший в open source. Хотя он и совместим со Spring Boot https://openliberty.io/docs/latest/deploy-spring-boot.html, два факта говорят о том, что смысла так делать нет:
1) одна из главных фишек Open Liberty - полная поддержка Java EE/Microprofile. Это точно не про Spring.
2) среди встроенных серверов Spring Boot нет Open Liberty в отличие от остальных четырех кандидатов.
Тоже побыстрее Tomcat, поддерживает модульность (а это необходимое условие при полной поддержке Java EE).

Остаются два кандидата - Jetty и Undertow.

Undertow - полностью JBoss Undertow - тоже бывшая коммерческая разработка, ушедшая в open source. Архитектурно сделана в неблокирующем стиле а-ля Netty, но с поддержкой сервлетов (Spring Web MVC). Что должно положительно сказаться на производительности. Плюс можно плавно мигрировать с кода в классическом стиле к реактивному. Минус по сути один - мало распространена, меньше сообщество. Да, и уязвимостей мало https://www.cve.org/CVERecord/SearchResults?query=undertow

И наконец Jetty. Архитектура классическая, как и у Tomcat. Разработчики делают фокус на модульной структуре: даже поддержка http (обычного, HTTP v1) обеспечивается модулем и может быть отключена. Кому интересно - вот список модулей из стандартной поставки: https://jetty.org/docs/jetty/12.1/operations-guide/modules/standard.html
Сообщество поменьше, чем у Tomcat, но достаточно большое, учитывая 20 лет на рынке. Уязвимостей сильно меньше в этом году https://www.cve.org/CVERecord/SearchResults?query=Jetty, при сравнимом количестве в 2024.

Вывод: а надо ли куда-то переходить? Для Spring Web MVC приложения большой разницы в производительности, потреблении памяти и надежности на ПРОМ я не ожидаю. Как я говорил - все сервера production ready. Но в плане уязвимостей - возможно, с Jetty жизнь станет немного спокойнее. Не ложное ли это успокоение - может "хакеры" еще не добрались до Jetty? Время покажет, но учитывая 20 лет на рынке ... очень может быть, что и нет, не ложное.

P.S. Интересно, что и IBM, и Redhat (JBoss)) пошли одним путем - выделить ядро своего сервера в отдельный lite компонент и сделать его open source.

#java #web #servlet
Если LLM не понимает твой код (процесс)...

В продолжение поста про мысль о том, что код, который не понимает LLM - плохой код.

Пишу сейчас агента, постоянно сталкиваются с скажем так ... не очень хорошей и совсем не стабильной работой LLM.
Начиная с какого-то уровня сложности промта LLM глючит - игнорирует прямые указания, выполняет лишние действия.
Первая мысль - ну тупая...)
Вторая - а может использовать LLM как своеобразный критерий качества аналитики и\или бизнес-процесса?
Если LLM глючит - аналитика не логичная, а процесс - кривой?

Причем и объяснение такому поведению модели есть. Если у нас сложный процесс, то у него большое значение цикломатической сложности - возможных путей выполнения программы. Это аналогия с кодом, т.к. в системном промте мы, пусть и более декларативно, тоже по сути пишем код. А работа LLM - это вероятностный процесс, т.е. на каждой развилке есть вероятность, что процесс пойдет не туда. Плюс код анализируется и выполняется последовательно, а промт - единовременно, и любой кусок пользовательского или системного промта может повлиять на план выполнения агента. И что в итоге мы получим ...?)

P.S. Вопрос конечно провокационный, но справедливости ради в попытках заставить LLM отвечать корректно я нашел ряд логических противоречий в промте. И перешел от 3 агентов к одному, т.к. в рамках одного проще поддерживать непротиворечивость промта.
P.P.S. Все же русский язык совсем не идеален для описания бизнес-логики.
..P.S. Как со всем этим делать мультиагентную систему, где логика пишется разными людьми и выполняется разными агентами - вопрос.

#llm #ai
Новости AI

1) появился инструмент сравнения разных LLM моделей - один забра запрос передаётся в 2 разные модели, скорость и качество ответа можно сравнить глазами. https://lmarena.ai/ Что интересно - доступны коммерческие LLM без регистрации и СМС, в смысле без VPN и оплаты

2) сейчас у большинства AI чатов появляется режим Research. Это ризонинг + поиск в интернете + какой-то набор tool для обработки полученных данных. Ещё из важного: составляется план исследования и дозапрашиваются непроходимые данные у пользователя. По сути это AI агент, заточенный под исследования.
Недавно тестировал такой режим у Mistral.
На мою просьбу сравнить скорость сборки Docker образов, модель не просто поискала в интернете тесты, а вначале уточнила сложность образа и возможность включить кэширование(!), после чего сделала вот такой план выполнения запроса:
1) создать docker файлы с нужным настройками
2) сформировать команду для измерения времени сборки для всех видов сборки
3) запустить команду n раз, посчитать среднее

В ответе кроме плана и таблицы с результатами (среднее, max, min), была конфигурация тестового сервера (!!!), описание плюсов и минусов всех инструментов сборки и рекомендации по их использованию.

Думаю - вот до чего техника дошла. И LLM модель, и поиск в вебе, и ещё виртуалку для выполнения задачи подняли. Реально - AI джун. И все бесплатно.
Но червячок сомнения точит... Спросил у модели - а ты реально виртуалку подняла для теста? Нет, говорит, не умею я такого. А откуда цифры тогда, дай источник? Нет источника, синтезировала цифры. Вот тебе ссылки, ищи там, результаты неточные (((
Вывод:
а) LLM модели врут
б) очень хотелось бы иметь такого джуна.

Из хорошего - инструмент доступен без VPN и есть бесплатные попытки. Полезен, если для выполнения задачи достаточно поиска. Ещё может с планом исследования помочь. Что интересно: неделю назад было 10 попыток в месяц, сейчас стало 5, кроме того появилось разделение по скорости - одна попытка быстрая, 4 - медленные. Экономика должна быть экономной)

3) OpenRouter - веб-сервис, являющийсф прокси-адаптером к куче LLM моделей с ChatGPT API. Область применения:
а) запуск кода, написанного для OpenAPI, на других моделях
б) динамический выбор модели в зависимости от задачи/цены без необходимости хранить кучу разных credentials у себя
в) отказоустойчивость.
Из хорошего - много моделей и небольшая наценка.
Из плохого - недавно закрыли доступ из России.
Из интересного - вот тут можно глянуть рейтинг моделей, используемых для разработки https://openrouter.ai/rankings?category=programming#categories
Ясно, что он искажён в части доли ChatGPT. Т.к. если тебя полностью устраивает ChatGPT, то ты не будешь использовать прокси. Но все же интересно)

#ai #llm #ai_agents
😁1
Всем привет!

Для IntelliJ IDEA появился новый плагин - Spring Debugger.
Цель создания понятна - мир бинов типичного Spring приложения огромен и запутан. Периодически что-то ломается, возникают вопросы типа такого: "Почему (не)поднялся тот или иной бин"?

Как всегда - статья: https://habr.com/ru/companies/spring_aio/articles/924550/

И кратко то, что меня зацепило:
1) в окне Spring показывает какие из бинов не инстанцированы или заменены моком
2) во время выполнения показывает фактически значения настроек в application.properties(yml) - там где они переопределены или рассчитаны
3) при заходе в метод подсказывает, если он выполняется внутри транзакции и детали транзакции: уровень изоляции, propagation, место начала
4) там же отображает состояние JPA кэша первого уровня в реальном времени
5) REPL для Spring-контекста: в окне Threads&Variables можно искать не только локальные объекты, но и любые Spring бины из контекста, с автодополнением и вызовом методов.
6) там же можно вбить имя настройки и увидеть откуда оно считалось (главное не забыть переключить область поиска с Java на Spring Properties).

Увы, доступен только в Ultimate. Если это не препятствие - рекомендую.

P.S. Вначале создаем Spring приложения с кучей бинов, потом героически преодолеваем сложность)

#idea #ide #debug #dropapp
UUID ключи в PostgreSQL

Я уже писал про версии UUID https://t.me/javaKotlinDevOps/264
Особенно интересной выглядит 7-я версия для использования в БД для построения индексов по двум причинам:
1) позволяет сортировать записи по времени создания
2) значение содержит метку времени, ее можно извлечь
Ну и эффект, наблюдаемый только в БД - записи ложатся последовательно в индексах и, соответственно, partition благодаря тому, что генерируются монотонно возрастающие значения.

Стандарт был принят в мае 2024 года https://datatracker.ietf.org/doc/rfc9562/

И не прошло и полгода (прошел год, но в мире БД это кажется даже быстро) и появляется PostgreSQL 18 c нативной поддержкой UUID v7 (функции uuidv7() и uuid_extract_timestamp) https://habr.com/ru/companies/spring_aio/articles/946168/

P.S. Если вчитаться в стандарт - попадаешь в кроличью нору:
1) для целей безопасности метка времени обрезается до миллисекунд
2) но чтобы получить возрастающие значения используется счетчик
3) счетчик инициализируется случайным числом, во избежание коллизий
4) есть защита от переполнения счетчика - допустимо использовать как счетчик ту часть метки времени, которую мы обнулили ранее, главное не перейти за границы миллисекунды. Если и этого не хватит - вопрос...
5) генератор должен хранить время t0, чтобы при переводе времени продолжать использовать исходное время и значения были уникальными и монотонно возрастающими
...

#postgresql #uuid
👀2
Небольшая заметка.

Мы обсуждаем, как хорошо AI пишет код. Но люди его используют совсем не для этого: https://t-j.ru/news/how-people-use-chatgpt

Это я, к тому, для каких задач его будут оптимизировать.

С другой стороны: да, 4% казалось бы немного. Но если сравнить с обычным поиском, то рост раза в 2. Точных цифр по доле запросов по разработке в поисковом трафике нет, но тот же ChatGPT дает неплохую оценку исходя из числа разработчиков и среднего числа их запросов в день.

#ai
Как быстрее погрузиться в код?

Речь про существующий микросервис и нового разработчика.
Я уже писал, что JavaDoc (KDoc) не является обязательным для каждого метода\поля или класса (как минимум для бизнес-приложения, общие библиотеки - особый кейс), т.к. документацию никто не читает.
А что же тогда будет документацией? Например, тесты. Их конечно тоже новичок не будет читать на 100%, но во-первых их и так нужно писать, а во-вторых - при рефакторинге падающий тест покажет, что забыли поправить, а в целом любой существующий тест изменяемого класса покажет, как он работает.

А недавно я нашел еще один полезный способ задокументировать микросервис так, чтобы этой "документацией" пользовались.
Начну немного издалека. Есть такая ИТ консалтинговая компания как Thoughtworks. Ну есть и есть, где мы и где консалтинг. Но там работает такой небезызвестный человек, как Мартин Фаулер. Главный научным руководителем https://www.thoughtworks.com/profiles/leaders/martin-fowler
А это внушает некий уровень доверия.
Так вот, компания ведет реестр технологий а-ля техрадар.
И в текущей его версии есть такая штука https://www.thoughtworks.com/en-de/radar/techniques/api-request-collection-as-api-product-artifact
как коллекция API запросов как артефакт продукта.
На самом деле мысль лежит на поверхности, я уже достаточно давно практикую прихранивание запросов в формате IDEA api collection вместе с исходниками в тех проектах, над которыми приходилось работать. Да, над форматом стоит подумать отдельно, возможно Insomnia будет по-универсальнее, зависит от команды и организации. Но сама идея мне очень нравится. Такой документацией точно будут пользоваться.

P.S. Кто ее должен делать - разработчики или тестировщики и нужно ли шарить коллекцию между ними - тоже вопрос для обсуждения. В идеале - думаю, что да.

P.P.S. Да, когда я говорю про артефакт продукта - это значит мало ее сделать, ее нужно поддерживать в актуальном состоянии.

#api #onbording #documentation
🔥1
Основные проблемы AI в разработке.

Я вижу две основные проблемы.

Первая - принципиально недетерминированный ответ как отражение вероятностной природы LLM. Если в креативных задачах это плюс, но в разработке скорее минус.

Вторая - естественный язык не самое лучшее API из-за своей неоднозначности.

И для второй, а частично и для первой проблемы есть решение - паттерн structured output. Суть проста - мы говорим модели, в каком виде хотели бы получить ответ. Это может быть JSON схема или класс Response. Базовый формат - JSON, но он на уровне библиотеки легко трансформируется в класс для большинства языков программирования. Ключевой момент - вызов модели должен вернуть правильный по структуре JSON с вероятностью 100%. И далее его можно или без лишних проверок парсить и передавать на вход следующему методу.

Реализован паттерн должен быть в самой модели, так как на уровне библиотеки или промта гарантии 100% соответствия получить нельзя.

Вот статья с примером использования:
https://habr.com/ru/articles/923096

P.S. Паттерны есть везде, коллекция AI паттернов постепенно растёт)

#ai #llm
RestTemplate is dead, baby)))

Spring наконец-то решили задепрекейтить RestTemplate.
Пруф: https://spring.io/blog/2025/09/30/the-state-of-http-clients-in-spring

Его замены в fluent стиле: RestClient для синхронного и WebCLient для асинхронного взаимодействия.
Видимо, команда Spring таки выпилила его из компонентов фреймворка и теперь предлагает это сделать всем остальным)

На самом деле я немного добавил сенсационности в пост.
А реальная хронология событий планируется такая:
- в ноябре этого года (Spring 7.0) будет объявлено о том, что компонент deprecated
- формально deprecated он станет в ноябре 2026 года (Spring 7.1)
- выпилят в Spring 8.0 где-то в 27 году.

Это мир Java == мир обратной совместимости)

#spring #web
👍2
Языки программирования общего назначения?

Java, Python, C, Go. Формально, технически - да, все это универсальные языки, которые можно применять в любой, задача. А фактически?

Говорим Python - подразумеваем Data Science, ML и AI.
Go захватил разработку крипты. Плюс операторы в k8s.
Kotlin - от 70 до 90% приложений в Google Play (топовых приложений если быть точным, т.к. есть "хвост" легаси)
Похожая картина у Swift - примерно 60% в iOS (доля бинпрников в iOS 17).
C# - нативные Windows приложения (Delphi и VB.NET эту битву проиграли).
Groovy нашел свою нишу в Jenkins как DSL (Gradle еще, но там его теснит Kotlin, да и не должны Gradle скрипты быть большими).
Lua - язык плагинов (Nginx, Tarantool) и скриптовый язык для игр. То бишь - король DSL.
Драйвера пишут на C (до сих пор ли? Раньше так было).

Да, экосистема (библиотеки, фреймворки, документация, сообщество) рулит)

И вопрос - что я забыл?

#lang
Небольшой забавный (и при этом грустный) факт о JVM.

Для запуска Hello world приложения на Java JVM загружает 450 классов.

Пруф: https://inside.java/2025/01/28/jvm-start-up/


#jvm #fun_facts
😱4
Если IDEA легла при старте. Или mini IDEA troobleshooting guide.

Что можно сделать?

Вариант номер ноль - обругать нехорошими словами разработчиков IDE и откатиться на предыдущую версию. Хотя, разработчики IDE могут быть не виноваты, о чем ниже)
Если вас этот вариант не устраивает - вот на что стоит обратить внимание.

Предусловие - надо вспомнить где у вас хранятся настройки IDEA. По умолчанию на примере Windows это %USERDATA%\AppData\Local\xxx\yyy, xxx - это JetBrains\GIGAIDE\..., а yyy - имя IDE.
Но через idea.properties это место можно переопределить.

И так.
1) Логи. По умолчанию лежат в %USERDATA%\AppData\Local\xxx\yyy\log\idea.log
В логах стоит обратить внимание на исключения. Как ни странно, искать их надо по SEVERE, а не ERROR
Возможно из исключения будет сразу понятна причина.

2) Плагины. Часто в исключении есть какие-то классы, но за что они отвечают - не ясно. Но если перед исключением есть строчка
Plugin to blame: xxx,
то предполагаемый виновник найден.
Очень часто это новый плагин или его новая версия.
Его надо отключить. Но IDE не стартует, и настройки в UI недоступны.
Не беда - внешние плагины можно отключить удалив соответствующую папку из %USERDATA%\AppData\Roaming\xxx\yyy\plugins.
Бывают сбои и во встроенных (bundled) плагинах, поэтому есть второй способ: добавить id плагина в файл %USERDATA%\AppData\Roaming\xxx\yyy\disabled_plugins.txt
Важно - id, а не имя. id это по сути grouId артифакта, найти его можно в логе.

3) Текущий проект. У меня были кейсы, когда даже с плагином с утечкой памяти, сжирающим 6, 8, 16 Гб - т.е. все что дадут - удавалось запустить IDE открыв пустой проект. Но IDEA по умолчанию открывает последние проекты. Вариант решения - переименовать папку, чтобы она их не нашла.

4) Опции запуска. https://www.jetbrains.com/help/idea/working-with-the-ide-features-from-command-line.html#arguments
Могут помочь решить проблему следующие:
а) disableNonBundledPlugins - запуск IDE без внешних плагинов
б) dontReopenProjects - более элегантный вариант открыть IDEA без последних проектов

5) Память. Если в логах есть OutOfMemoryError - можно попробовать увеличить Heap для IDEA. Почему можно попробовать - потому что это не панацея, при утечке памяти не поможет.
Второй вопрос - как увеличить? Через idea64.exe.vmoptions.
А если не хватает прав его поправить?
Есть его "профильный" (лежащий в профиле пользователя) двойник %USERDATA%\AppData\Roaming\xxx\yyy\idea64.exe.vmoptions.
Рекомендую использовать его, особенно если у вас настройки IDEA в кастомной папке, не меняющейся от версии к версии.

6) thread dump и heap dump. Больше помогут разрабам IDE, но глянуть можно.
Создаются в двух случаях.
а) При каждом зависании (freeze) создаются в %USERDATA%\AppData\Local\xxx\yyy\log\threadDumps-freeze-zzz
б) при OutOfMemory с включенной опцией -XX:+HeapDumpOnOutOfMemoryError (а в idea64.exe.vmoptions она по умолчанию есть) в %USERDATA% создается heapdump и лог, включающий threaddumps

На сегодня все, если найду еще интересные лайфхаки - сделаю новый пост.

#idea #ide #troubleshooting
👍2
Минутка философии на канале)
На тему AI конечно же)

Вопрос - не является ли массовое внедрение AI сейчас (причем со словами везде и надо еще вчера) временным хайпом?

Ответ - даже если и является, очень может быть, что является, AI из разработки уже не уйдет. Как не ушли Agile, DevOps, микросервисы.

Почему - потому что уже на текущем уровне инструмент позволяет автоматизировать рутину малой кровью. Не все модели, не любые задачи - но рабочие кейсы есть. Описание чужого кода, типовой код (маппинг), каркас приложения, базовый набор тестов, замена поиска... И их будет больше.

Вывод - изучать надо)

#ai
👍3💯2
Новая LTS Java.

Я о Java 25.
Вышла не вчера, поэтому также вышла и хорошая статья с обзором нововведений https://habr.com/ru/companies/T1Holding/articles/946778/.
Там даже табличка включения новых фич от 21 до 25 версии есть. И примеры кода - было\стало.
И от меня как всегда пару комментариев)

Для начала бросаются в глаза две фичи со "странным" названием Quantum-Resistant ...
Почему бросаются - квантовые компьютеры ожидаются в промышленном использовании в течение 10+ лет, а устойчивые к взлому квантовым компьютером алгоритмы в Java появились уже сейчас.
С - стратегия.
Б - банковское ПО)

Три фичи со словами Ahead-of-Time, главная из них - Ahead-of-Time Class Loading & Linking.
Это дальнейшее развитие темы CDS https://t.me/javaKotlinDevOps/316
Т.е. ускорение старта приложения.
Если CDS убирает этап верификации классов сохраняя в архиве уже проверенные классы,
то Ahead-of-Time Class Loading & Linking как следует из названия сохраняет всю необходимую для работы с классами информацию. Так сказать в распакованном виде, поэтому ее сразу можно грузить в Metaspace.
Одно но: набор классов у всех разный, поэтому нужно запустить приложение в тестовом режиме и собрать данные по актуальным классам, которые и будут сохранены в архиве.
Заодно сохраняется и статистика их использования (Ahead-of-Time Method Profiling), что позволяет при старте JVM сразу запустить компиляцию часто используемых методов.
Последняя фича - это offline Profile-Guided Optimization https://t.me/javaKotlinDevOps/315, которая ранее была killer feature коммерческих JVM: Azul ReadyNow и GraalVM Enterprise Native Image.
Итоговое ускорение загрузки: 42% vs 33% у CDS https://www.happycoders.eu/java/ahead-of-time-class-loading-and-linking/

Есть еще две оптимизационные фичи: Compact Object Headers и Linking Run-Time Images without JMODs.
Первая уменьшает размер любого объекта в памяти, оптимизируя заголовки. Вторая - уменьшает объем JDK, убирая оттуда JMOD файлы. JMOD появились вместе с модулями Java как развитие jar.
И классы в jmod файлах уже есть в JDK, т.е. имеем дублирование. Сейчас его убрали, размер JDK стал меньше на 25%. Важно в облаках с тысячами микросервисов.

На самом деле технология модулей в Java до сих пор не прижилась в коммерческой разработке, но команда Java не сдается)
Module Import Declarations - можно разом импортировать все классы в модуле. С одной стороны загрязняется область видимости, с другой - удобно.

Markdown Documentation Comments: Markdown - стандарт документации в ИТ в целом, получаем больше возможностей в JavaDoc. Да, JavaDoc нужны не всегда, но пригодится.

Фичи с JFR в названии - допилен профайлер: меньше влияние на исполнение кода (JFR Cooperative Sampling), больше данных (JFR Method Timing & Tracing).

Unnamed Variables & Patterns: _ (подчеркивание) обозначает для компилятора и валидаторов неиспользуемую переменную. Java пополнила длинный список языков, где это уже есть)

Scoped Values - более безопасный вариант Thread Local.

Также дошли до prod ready версии фичи из моего поста про Java 22 https://t.me/javaKotlinDevOps/278
* Launch Multi-File Source-Code Programs
* Implicitly Declared Classes and Instance Main Methods
* Stream Gatherers
* Class-File API
* Statements before super

Итого - решаются проблемы с производительностью и объемом, допиливается функционал (стримы, модули, JFR, Thread Local, GC), стандартизируются API (Class-File API), немного синтаксического сахара (_).

А String templates https://t.me/javaKotlinDevOps/246 выкинули. Слишком отличается от мэйнстрима, я про идею процессора STR."xxx", обрабатывающего строки

#java #jdk #java_new_version
Серия: "Хозяйке на заметку" про PostgreSQL.
А точнее про создание индексов.

CREATE INDEX table_idx ON books (title) 


Вроде все просто.

Но есть ряд интересных опций.
1) CONCURRENTLY
Получается так:
CREATE INDEX CONCURRENTLY table_idx ON books (title)  

Когда нужно - всегда если накат идет на активное плечо ПРОМа. Опция не блокирует изменение таблицы пользователя. Минусы: команда выполняется дольше.

2) INCLUDE
Известно, что чтение значения индекса работает быстрее, т.к. это значение хранится в индексе, не нужно ходить в таблицу. Но кроме того в индекс можно положить любые другие значения из записи таблицы. Можно, но осторожно, т.к. это в любом случае дублирование данных. Эффект надо подтверждать на НТ.
Получаем:
CREATE INDEX table_idx ON books (title) INCLUDE (isbn)


3) WHERE
Позволяет поместить в индекс не все значения столбца, имеющиеся в таблице.
Решает следующие кейсы:
а) низкая селективность индекса: выбирает только значения с высокой селективностью
б) экономия места в памяти (и возможно в каких-то случаях на диске): выбираем в индекс только необходимое
в) частичная уникальность: если нужен уникальный индекс, но он соблюдается не для всех значений.
Выглядит так:
CREATE INDEX table_idx ON books (title) WHERE country = 'Russia'


P.S. Еще есть интересная опция USING, позволяющая использовать разные типы индексов (по умолчанию в PostgreSQL используется btree), но это отдельная тема)

Детали в официальной документации https://www.postgresql.org/docs/current/sql-createindex.html

#postgresql #db #performance
4
Рубрика "Виртуальные споры с Бугаенко")))

Егор любит провокативные посты, причём всегда (почти всегда?) в таких постах есть здравая мысль, заставляющая задуматься о том, как я пишу код. И этим они хороши)

Сейчас набрел на 2 поста о переменных:
https://www.yegor256.com/2015/01/12/compound-name-is-code-smell.html
https://www.yegor256.com/2015/09/01/redundant-variables-are-evil.html

Краткое содержание первого: составные имена переменных - типа flieName - это code smell. Аргумент - если имя пришлось сделать из 2+ слов, то это значит у нам слишком большая область видимости и нарушение Single Responsibility.
Тут в целом да. Я за небольшие методы, компилятор их оптимизирует. И такой критерий простоты метода как простые имена переменных - не очевидно, не единственный, но красиво.
А вот если говорить про имена полей класса, то тут скорее нет. Да, к классам тоже применим Single Responsibility, да, в имени поля не должно повторяться имя класса. Но видится, что строгое следование данному правилу усугубит "ООП-болезнь" - бесконечное дробление классов. А так мы отходим от структуры предметной области и усложняем чтение кода из-за прыжков между файлами. Вспомним, что разработка - искусство компромиссов)

Второй пост о том, что вынесение результата выполнения строчки кода в одноразовую локальную переменную - зло. Т.к. появляется 2+ строчки вместо одной, и ухудшается читаемость.
С одной стороны да. Но если у нас есть вызов метода, он уже достаточно сложный, а расчёт значений его параметров увеличивает длину строки кода до 100, 200... символов?
Да, можно выделить часть кода в отдельные методы. Методы тоже одноразовые...
А тогда какая разница?
Поэтому я бы сказал так: автоматом выносить все расчитываемые знпченич в переменные точно не надо.
Но и обратное не верно. Иногда такой приём улучшает читаемость, и в этом случае оправдан. Снова компромиссы)))

#clean_code #dev_compromises
Снова про индексы.

Пост навеян вот этой статьей: https://vladmihalcea.com/index-selectivity/
Рекомендую прочитать, она короткая.

Многие знают про селективность индексов. На собесах в ответ на вопрос: на какие поля нужно делать индексы - я часто слышу про низкую селективность.
Суть в том, что если в колонке значения сильно не уникальные - хорошие примеры это boolean и enum - то индекс делать не надо.

Вообще говоря да, это так. Ответ верный.

Но есть нюанс. Полный ответ такой. Проблема такого индекса не в том, что БД будет неэффективно работать. БД после первого же запроса с использованием индекса поймет, что его стоимость выше, чем у full scan. И переключит все оставшиеся запросы на full scan.
А вот в чем мы точно проиграем - индекс съест место на диске и замедлит вставку. И что более важно: введет в заблуждение разработчика, т.к. создавая индекс он очевидно хочет решить с помощью него какую-то проблему (потенциальную?) с производительностью. А индекс по факту просто не работает.

P.S. И да, если по каким-то значениям в столбце селективность хорошая - поможет частичный индекс (WHERE в индексе).

P.P.S Сломать БД сложнее, чем кажется) Но все в ваших руках) И быстрее это можно сделать отсутствием нужно индекса, чем лишним индексом.

#db #performance
Регулярная рубрика - новости AI.

Нашел очередную статью про RAG https://habr.com/ru/companies/raft/articles/954158/
Казалось бы, нашел и нашел.
Но что интересно.
Вот есть AI. AI агент для примера.
Он общается с LLM.
LLM бывают разные.
Можно прикрутить AI proxy для совместимости по API.
А еще есть разные фреймворки для построения агентов.
Агент вызывает какие-то тулы.
Или MCP сервера по некому стандартизированному протоколу.
Или другого агента, для этого тоже есть стандартизированные протоколы.
Как источник домен-специфичных данных агент использует RAG.
RAG - это векторное хранилище, они бывают разные. Как специализированные, так и в виде расширения того же PotgreSQL.
Плюс есть технология преобразования данных (текстовых как правило, но не только) в векторный формат (embedding). Это тоже разные специализированные модели (но не те модели, что обрабатывают запрос пользователя).
Плюс есть технология разбиения данных на части (chunks), т.к. поиск по RAG - это сравнение векторов. Поэтому размер вектора для сравнения должен быть конечен, а документы в теории могут весить многие мегабайты.
Так вот. Даже для разбиения докумнетов на chunks уже появилось несколько конкурирующих библиотек, про это статья в начале поста.

О чем это говорит? Растет экосистема. Т.е. технология LLM потихоньку приходит к своей зрелости.

P.S. И поспорю сам с собой: за этот год по словам компетентных людей (я только учусь) сменилось три (!) принципа построения AI агентов.

#ai #rag
LLM как серебряная пуля?

Конечно же нет.
А если серьезно - что не умеет LLM?

1) выдавать актуальную информацию. Фиксится подключением веб-поиска

2) выдавать 100% точные ответы. LLM вероятностна по своей природе, поэтому даже самая мощная модель с огромным контекстным окном с выверенным промтом может галлюцинировать

3) отвечать на доменноспецифичные вопросы. Фиксится RAG, куда закачивается доменная специфика

4) выполнять сложные вычисления. Опять же LLM - статистический вычислитель, а не математический. Решается вынесением вычислений в тулы

5) работать с большими объёмами информации. Над этим - контекстное окно - работают все разработчики LLM, окно уже превышает 1 млн токенов, но в любом случае оно конечно. А ещё токены стоят денег. Альтернативныое решение - помещение больших документов в RAG, чтобы не гонять их туда сюда, или разбиение на части (chunks) перед взаимодействием с LLM.

6) формировать JSON. Ладно, если быть точным - плохо умеет. Как ни странно, уменьшение размера и упрощение шаблона ответа может ускорить его генерацию. structured output не спасает

7) приготовить еду, изготовить телефон, построить дом. В общем взаимодействовать с физическим миром напрямую

8) понимать людей. Да, модель отвечает на любой вопрос. Ну почти любой, цензура как никак) Да, кому-то AI уже заменяет "кожаного" собеседника. Но в описанных случаях будет получен некий среднестатистический ответ, который должен порадовать спрашивающего. А если ваш вопрос уникальный и сложный, то промт должен быть непротиворечивым, компактным и структурированным. Так ли общаются люди? Да нет)))

9) изобретать, ставить задачи, мыслить. Опять же - LLM - это просто статистическая машина, обученная на большом объёме данных.

Так что кожаным мешками работа ещё найдётся.

P.S. и не только строителя дата-центров)

#ai
👍3