Когда я ещё студентом пришёл в работать в маленькую фирму по модернизации больших металлообрабатывающих станков, мне повезло работать под руководством опытного советского инженера-станкостроителя Бориса Леонидовича Хоменко. А он, в свою очередь, в силу возраста успел поработать с людьми закалки конца 40-ых, 50-ых и начала 60-ых годов 🕰
В те времена станкостроение было одной из ключевых отраслей промышленности, ведь от него напрямую зависели другие жизненно важные отрасли. Трудившимся там людям, по сути, нужно было в кратчайшие сроки сначала восстановить огромную страну из послевоенных руин, а потом сразу же вывести её промышленность на новый технологический уровень 📊
Стоит ли говорить, что они работали под огромным давлением со всех сторон? Нынешние дедлайны по спринтам и релизам кажутся детскими шалостями по сравнению с той нагрузкой и ответственностью, которую несли тогда они 🗿
Так вот Борис Леонидович получил от них и передал мне простую, но мудрую мысль, которая, как мне кажется, формирует правильное отношение к длительной работе под большой нагрузкой. Звучит она так:
А ведь и правда: зачастую слова "делай быстро" заставляют нас спешить. На первых порах это бывает оправданно, но уже скоро выясняется, что на длинной дистанции такой темп нам не по силам; что спешка порождает много ошибок; что сама работа уже, как минимум, не в радость, а то и вовсе уже противна. Всё это приводит к постепенному затуханию (выгоранию) и вынужденной остановке, часто на непредсказуемый срок 🕳
Слова "без остановок" не значат, что отдых вреден, разумеется. Они значат, что на больших объёмах работ беспорядочные перерывы зачастую вредят больше, чем не очень высокий темп выполнения. Подобно этому равномерно и неспешно бегущий марафонец достигает финиша раньше, чем равный ему по силам товарищ, рванувший со старта, но вынужденный много раз переходить на шаг, чтобы перевести дух 🏃♂️
Вероятно, за этими простыми словами стоит немало серьёзных историй тех суровых времён 🤔
Если вам тоже доводилось слышать от своих наставников/руководителей мудрые мысли, надолго запавшие в память, поделитесь, пожалуйста, в комментариях — пусть о них узнает больше людей 📢
В те времена станкостроение было одной из ключевых отраслей промышленности, ведь от него напрямую зависели другие жизненно важные отрасли. Трудившимся там людям, по сути, нужно было в кратчайшие сроки сначала восстановить огромную страну из послевоенных руин, а потом сразу же вывести её промышленность на новый технологический уровень 📊
Стоит ли говорить, что они работали под огромным давлением со всех сторон? Нынешние дедлайны по спринтам и релизам кажутся детскими шалостями по сравнению с той нагрузкой и ответственностью, которую несли тогда они 🗿
Так вот Борис Леонидович получил от них и передал мне простую, но мудрую мысль, которая, как мне кажется, формирует правильное отношение к длительной работе под большой нагрузкой. Звучит она так:
Что такое "делать быстро"?
Это значит делать не торопясь, но без остановок.
А ведь и правда: зачастую слова "делай быстро" заставляют нас спешить. На первых порах это бывает оправданно, но уже скоро выясняется, что на длинной дистанции такой темп нам не по силам; что спешка порождает много ошибок; что сама работа уже, как минимум, не в радость, а то и вовсе уже противна. Всё это приводит к постепенному затуханию (выгоранию) и вынужденной остановке, часто на непредсказуемый срок 🕳
Слова "без остановок" не значат, что отдых вреден, разумеется. Они значат, что на больших объёмах работ беспорядочные перерывы зачастую вредят больше, чем не очень высокий темп выполнения. Подобно этому равномерно и неспешно бегущий марафонец достигает финиша раньше, чем равный ему по силам товарищ, рванувший со старта, но вынужденный много раз переходить на шаг, чтобы перевести дух 🏃♂️
Вероятно, за этими простыми словами стоит немало серьёзных историй тех суровых времён 🤔
Если вам тоже доводилось слышать от своих наставников/руководителей мудрые мысли, надолго запавшие в память, поделитесь, пожалуйста, в комментариях — пусть о них узнает больше людей 📢
🔥10👏8❤4
В блоге компании AxiomJDK на Хабре позавчера вышла статья Алексея Рагозина о работе с JDK Flight Recorder'ом из командной строки. Фишка статьи в том, что она не только рассказывает, как запускать/мониторить/останавливать записи JFR, но и как смотреть их результаты прямо на лету, т.е. без дампа в файлы с последующим открытием. Мне довелось немного поучаствовать в подготовке этой статьи; в основном, как рецензенту 🤓
Если кто не знает, Алексей — один из топовых российских экспертов по производительности JVM. Он пишет глубокие технические статьи, выступает с докладами, ведёт тренинги и сам разрабатывает инструменты для диагностики JVM. Кстати, его проект SJK (Swiss Java Knife) используется, например, в Apache Cassandra 💪🏼
Послезавтра, 13 ноября в 19:00 МСК Алексей проведёт открытый вебинар по работе с JFR из командной строки, но в отличие от статьи, там будет возможность в живую увидеть пример применения JFR к приложению на #Java 25, включая совсем свежие улучшения, вышедшие в этой версии в сентябре. Кто хочет быть на гребне прогресса, подключайтесь 📺
Если кто не знает, Алексей — один из топовых российских экспертов по производительности JVM. Он пишет глубокие технические статьи, выступает с докладами, ведёт тренинги и сам разрабатывает инструменты для диагностики JVM. Кстати, его проект SJK (Swiss Java Knife) используется, например, в Apache Cassandra 💪🏼
Послезавтра, 13 ноября в 19:00 МСК Алексей проведёт открытый вебинар по работе с JFR из командной строки, но в отличие от статьи, там будет возможность в живую увидеть пример применения JFR к приложению на #Java 25, включая совсем свежие улучшения, вышедшие в этой версии в сентябре. Кто хочет быть на гребне прогресса, подключайтесь 📺
Хабр
Работа с JDK Flight Recorder (JFR) из командной строки: инструмент для профилирования без графического интерфейса
Экосистема Java богата качественными инструментами для разработчиков, и средства профилирования и диагностики - не исключение. Существуют коммерческие профилировщики, есть встроенные инструменты...
🔥9
В продолжение темы про JFR ✈️
Вчера разбирался с забористым багом — барахлила асинхронная связь между двумя модулями приложения (на одной JVM): один обновлялся, а второй не всегда. Помимо нестабильности воспроизведения дело усложнялось тем, что проблема стреляла только на удалённом сервере заказчика. Короче, всё по классике😏
При помощи ряда экспериментов, интуиции и такой-то матери мне удалось выяснить, что один из асинхронно выполняемых методов прерывается из-за какого-то исключения. Но этого исключения не было в логах, потому что в методе не предусмотрели
, то есть отправлялся на исполнение в пул безо всякой обратной связи (что уже не хорошо, но это отдельная тема✍️)
И вот ситуация:
— исключение есть
— логов нет
— добавить логирование в код нельзя, потому что после перезапуска проблема опять перестанет повторяться.
"И как теперь что?" 🫤 (© Масяня)
К счастью, внутри JVM на выбросы исключений заведено отдельное событие для JDK Flight Recorder, оно называется
Запуск записи в моём случае выглядел так:
, где:
•
•
•
•
После старта записи я выполнил в приложении проблемное действие, а потом остановил запись вот таким заклинанием:
, где:
•
На выходе получился файл
Кажется, это неплохой пример применения JFR в сложной ситуации. Если бы не помог и он, можно было бы расчехлить BTrace, но давайте останемся в рамках приличия 🤭
Вчера разбирался с забористым багом — барахлила асинхронная связь между двумя модулями приложения (на одной JVM): один обновлялся, а второй не всегда. Помимо нестабильности воспроизведения дело усложнялось тем, что проблема стреляла только на удалённом сервере заказчика. Короче, всё по классике😏
При помощи ряда экспериментов, интуиции и такой-то матери мне удалось выяснить, что один из асинхронно выполняемых методов прерывается из-за какого-то исключения. Но этого исключения не было в логах, потому что в методе не предусмотрели
try/catch, а сам метод вызывался так:executorService.submit(this::fireBatchedEvents)
, то есть отправлялся на исполнение в пул безо всякой обратной связи (что уже не хорошо, но это отдельная тема✍️)
И вот ситуация:
— исключение есть
— логов нет
— добавить логирование в код нельзя, потому что после перезапуска проблема опять перестанет повторяться.
"И как теперь что?" 🫤 (© Масяня)
К счастью, внутри JVM на выбросы исключений заведено отдельное событие для JDK Flight Recorder, оно называется
jdk.JavaExceptionThrow. Если его включить и провести запись JFR во время проявления проблемы, то в ней (в записи) должны осесть данные обо всех исключениях, даже если само приложение их "глотает" 😋Запуск записи в моём случае выглядел так:
./jattach <PID> jcmd JFR.start settings=none +jdk.JavaExceptionThrow#enabled=true +jdk.JavaExceptionThrow#stackTrace=true
, где:
•
jattach — утилита для подключения к JVM, когда под рукой только JRE, а не JDK (в частности, нет jcmd);•
jcmd JFR.start settings=none — команда на старт записи с полностью выключенными событиями (чтобы не писать лишнего);•
+jdk.JavaExceptionThrow#enabled=true — флаг включения события JavaExceptionThrow. Символ "+" здесь нужен потому, что мы не меняем значение какой-то настройки из параметра settings (там же none), а добавляем его;•
+jdk.JavaExceptionThrow#stackTrace=true — флаг добавления стектрейсов к регистрируемым событиям; по умолчанию он снят, а без стектрейсов смотреть на исключения скучно.После старта записи я выполнил в приложении проблемное действие, а потом остановил запись вот таким заклинанием:
./jattach <PID> jcmd JFR.stop name=1 filename=error.jfr
, где:
•
jcmd JFR.stop name=1 — команда на останов конкретной записи (их может быть несколько). Имя записи можно либо задать явно при её запуске, либо посмотреть назначенное в ответе команды JFR.start 🚀На выходе получился файл
error.jfr, открыв который в Java Mission Control, удалось быстро отыскать пропавшее исключение и, главное, увидеть его стектрейс (хотя всего их там оказалось аж 320😳)Кажется, это неплохой пример применения JFR в сложной ситуации. Если бы не помог и он, можно было бы расчехлить BTrace, но давайте останемся в рамках приличия 🤭
Dev.java: The Destination for Java Developers
JDK Flight Recorder - Dev.java
Learn how to use JDK Flight Recorder to monitor, profile, and test your applications.
🔥17❤4👍4
Увидимся на Подлодке 🌊
В следующую среду, 19 ноября с 10:00 до 11:00 МСК будем общаться онлайн с ребятами из конференции Podlodka #Java Crew:
Всем, кому интересна тема анализа производительности и поиска "узких мест" в коде нагруженных приложений — милости просим 🙌🏼
В следующую среду, 19 ноября с 10:00 до 11:00 МСК будем общаться онлайн с ребятами из конференции Podlodka #Java Crew:
Интервью «Эволюция инструментов диагностики в Java»
В формате интервью поговорим с Владимиром про различные способы диагностики проблем производительности в Java, такие как JFR, NMT, Heap и Thread дампы, профилирование. Обсудим новшества в этой области, а также то, какие проблемы и тренды есть сейчас.
Всем, кому интересна тема анализа производительности и поиска "узких мест" в коде нагруженных приложений — милости просим 🙌🏼
podlodka.io
Онлайн-конференция Podlodka Java Crew, сезон #8
Недельное мероприятие от команды Podlodka: ежедневные интерактивные сессии в Zoom по актуальным проблемам java-разработки, нон-стоп общение с экспертами и звёздами индустрии, закрытое профессиональное сообщество в Telegram.
❤5🔥2
🎞 Новые полезные видео по #Java Performance
1. Вебинар про JFR @ CLI
Опубликована запись недавно упоминавшегося здесь вебинара Алексея Рагозина по работе с JFR из командной строки. Помимо наглядности, видео интересно обилием всяких неочевидных фишечек, например, что целевой процесс для команды
2. Интервью про инструменты диагностики в Java
Недавно анонсированное мною интервью на онлайн-конференции Podlodka Java Crew состоялось — там я рассказывал об инструментах диагностики Java-приложений и их новшествах. Здорово и приятно, что моим интервьюером был Дмитрий Константинов, по докладам которого я сам ещё недавно постигал премудрости чтения и записи в Cassandra. В ходе разговора мы затронули самые разные темы, начиная от древних как мир дампов потоков и заканчивая новейшими JEP'ами и применениями AI. Плюс к тому поговорили об обновлениях не только встроенных инструментов JDK (таких как JFR и NMT), но и популярных сторонних: async-profiler, Eclipse MAT, VisualVM. И хотя это было именно интервью, а не доклад, в ходе ответов я старался многое демонстрировать, поэтому запись желательно не только слушать 👀
Приятного просмотра! 🍿
1. Вебинар про JFR @ CLI
Опубликована запись недавно упоминавшегося здесь вебинара Алексея Рагозина по работе с JFR из командной строки. Помимо наглядности, видео интересно обилием всяких неочевидных фишечек, например, что целевой процесс для команды
jcmd можно указать не только по старинке через его PID, но и простым именем главного Java-класса (в котором объявлен метод main). Для тех отважных, кто решится повторить эксперименты вебинара самостоятельно, Алексей оставил небольшую текстовую инструкцию — всего-то 57 шагов 🫠2. Интервью про инструменты диагностики в Java
Недавно анонсированное мною интервью на онлайн-конференции Podlodka Java Crew состоялось — там я рассказывал об инструментах диагностики Java-приложений и их новшествах. Здорово и приятно, что моим интервьюером был Дмитрий Константинов, по докладам которого я сам ещё недавно постигал премудрости чтения и записи в Cassandra. В ходе разговора мы затронули самые разные темы, начиная от древних как мир дампов потоков и заканчивая новейшими JEP'ами и применениями AI. Плюс к тому поговорили об обновлениях не только встроенных инструментов JDK (таких как JFR и NMT), но и популярных сторонних: async-profiler, Eclipse MAT, VisualVM. И хотя это было именно интервью, а не доклад, в ходе ответов я старался многое демонстрировать, поэтому запись желательно не только слушать 👀
Приятного просмотра! 🍿
YouTube
Интервью: Эволюция инструментов диагностики в Java / Владимир Плизга (Tibbo Systems)
В формате интервью поговорим с Владимиром про различные способы диагностики проблем производительности в Java, такие как JFR, NMT, Heap и Thread дампы, профилирование. Обсудим новшества в этой области, а также то, какие проблемы и тренды есть сейчас.
Понравилось…
Понравилось…
👍6🔥4❤3
Пост-выходной впрыск новостей про #спорт
Вдохновленный своим относительно успешным прохождением Томского лыжного марафона (50 км коньковым ходом) в марте этого года, я решил не бросать это гиблое дело и выбрал новую цель — купил слот на аналогичный марафон, только уже в Кемерово, 14 марта. Старт называется KuzbasSki 🎯
Ту дистанцию в марте удалось "оформить" за 2:55:56 — во многом благодаря отличной погоде и сравнительно небольшому набору высоты (≈470 м). А вот на Кузбассе получить такой результат удастся едва ли, так как с погодой там часто бывают "сюрпризы", да и рельеф куда более забористый — набор ≈800 м 🏔
Но я всё продумал: специально взял слот заранее, чтобы не только успеть как следует подготовиться, но и передумать и слиться, а у вас было время забыть про этот пост и потом не срамотить меня за него🤪
Вдохновленный своим относительно успешным прохождением Томского лыжного марафона (50 км коньковым ходом) в марте этого года, я решил не бросать это гиблое дело и выбрал новую цель — купил слот на аналогичный марафон, только уже в Кемерово, 14 марта. Старт называется KuzbasSki 🎯
Ту дистанцию в марте удалось "оформить" за 2:55:56 — во многом благодаря отличной погоде и сравнительно небольшому набору высоты (≈470 м). А вот на Кузбассе получить такой результат удастся едва ли, так как с погодой там часто бывают "сюрпризы", да и рельеф куда более забористый — набор ≈800 м 🏔
Но я всё продумал: специально взял слот заранее, чтобы не только успеть как следует подготовиться, но и передумать и слиться, а у вас было время забыть про этот пост и потом не срамотить меня за него🤪
👍9😁1
Как быстро растут детишки фреймворки 🌱
Кажется, ещё недавно я рассказывал со сцены на Joker в Петербурге о граблях обновления #SpringBoot c версии 1 на 2. Но оказывается прошло семь лет, и вот намедни был объявлен официальный релиз версии Spring Boot 4.0. Любопытно, что в этот же день на онлайн-конференции Подлодка был доклад про переход на эту версию; ребята здорово подгадали 👨🏫
В документе Spring Boot 4.0 Release Notes одной из первых идёт весьма обтекаемая формулировка:
Как изящно они обошли фразу "вы офигеете разгребать поломки", не правда ли? 😉
Впрочем, наверняка опыт у всех будет разным. Судя по текущему Migration Guide, который в эти жаркие дни обновляется чуть ли не каждые несколько часов, основное веселье предстоит со стартерами ("кирпичиками" в Spring Boot), в том числе тестовыми, потому что одним из главных изменений в этой мажорной версии стала модуляризация фреймворка 🧱
Кроме того, похоже, не обойдётся и без развалов на этапе компиляции, так как многие классы разъехались по модульным пакетам, именуемым как
К счастью, такое масштабное обновление касается очень многих проектов, поэтому для него уже написана стопка рецептов на OpenRewrite, которая так и называется — Migrate to Spring Boot 4.0. По идее, она должна очень сильно упростить весь процесс, сведя его, по сути, к трём шагам:
1️⃣ Прописать в скрипте сборки рецепт (на примере
2️⃣ Запустить автомиграцию командой
3️⃣ Отревьюить получившиеся изменения и заставить их работать (чертыхаясь и понося уже не себя, а умный скрипт).
Какой способ обновления лучше — вручную или автоматически — каждый решает сам.
Но какой бы вы не выбрали, после завершения напишите, пожалуйста, в комментариях к посту или в ЛС, как у вас всё прошло — попробуем вместе собрать реальную картину обновлений 🖼
Кажется, ещё недавно я рассказывал со сцены на Joker в Петербурге о граблях обновления #SpringBoot c версии 1 на 2. Но оказывается прошло семь лет, и вот намедни был объявлен официальный релиз версии Spring Boot 4.0. Любопытно, что в этот же день на онлайн-конференции Подлодка был доклад про переход на эту версию; ребята здорово подгадали 👨🏫
В документе Spring Boot 4.0 Release Notes одной из первых идёт весьма обтекаемая формулировка:
... upgrading existing applications can be a little more involved that usual.
Как изящно они обошли фразу "вы офигеете разгребать поломки", не правда ли? 😉
Впрочем, наверняка опыт у всех будет разным. Судя по текущему Migration Guide, который в эти жаркие дни обновляется чуть ли не каждые несколько часов, основное веселье предстоит со стартерами ("кирпичиками" в Spring Boot), в том числе тестовыми, потому что одним из главных изменений в этой мажорной версии стала модуляризация фреймворка 🧱
Кроме того, похоже, не обойдётся и без развалов на этапе компиляции, так как многие классы разъехались по модульным пакетам, именуемым как
org.springframework.boot.<module>. Конечно, умная InetlliJ IDEA, скорее всего, быстро подскажет, на что нужно поменять импорты, но если в проекте много явных обращений к классам Spring Boot, потыкаться всё равно придётся 👉К счастью, такое масштабное обновление касается очень многих проектов, поэтому для него уже написана стопка рецептов на OpenRewrite, которая так и называется — Migrate to Spring Boot 4.0. По идее, она должна очень сильно упростить весь процесс, сведя его, по сути, к трём шагам:
1️⃣ Прописать в скрипте сборки рецепт (на примере
build.gradle):plugins {
id("org.openrewrite.rewrite") version("latest.release")
}
rewrite {
activeRecipe("org.openrewrite.java.spring.boot4.UpgradeSpringBoot_4_0")
setExportDatatables(true)
}
dependencies {
rewrite("org.openrewrite.recipe:rewrite-spring:6.19.0")
}2️⃣ Запустить автомиграцию командой
gradle rewriteRun.3️⃣ Отревьюить получившиеся изменения и заставить их работать (чертыхаясь и понося уже не себя, а умный скрипт).
Какой способ обновления лучше — вручную или автоматически — каждый решает сам.
Но какой бы вы не выбрали, после завершения напишите, пожалуйста, в комментариях к посту или в ЛС, как у вас всё прошло — попробуем вместе собрать реальную картину обновлений 🖼
Toparvion.Pro
Spring Boot 2: чего не пишут в release notes | Toparvion.Pro
Доклад о сложностях обновления базового фреймворка микросервисов
❤12🔥1
Skiing in the winter wonderland ❄️
🔥13😍9👍3💯1
Любопытно и порой не очень весело наблюдать за развитием некоторых программных инструментов. Например, когда-то я искал, на чём делать свою домашнюю страничку, и остановил выбор на Academic — шаблоне для сайтогенератора Hugo.
Выбрал, в том числе за простоту.
И вот как она преобразилась со временем (даты примерные, но состав точный)👇
Для локальной работы с сайтом на HugoBlox (ex. Wowchemy, ex. Academic) нужно:
2018: Hugo
2019: Hugo Extended
2021: Hugo Extended + Go
2023: Hugo Extended + Go + NodeJS
2025: Hugo Extended + Go + NodeJS + Tailwind CSS
Что дальше? Python? Rust? BrainF*ck?
Это ведь всё те же статически отдаваемые странички... Казалось бы 🤨
Выбрал, в том числе за простоту.
И вот как она преобразилась со временем (даты примерные, но состав точный)👇
Для локальной работы с сайтом на HugoBlox (ex. Wowchemy, ex. Academic) нужно:
2018: Hugo
2019: Hugo Extended
2021: Hugo Extended + Go
2023: Hugo Extended + Go + NodeJS
2025: Hugo Extended + Go + NodeJS + Tailwind CSS
Что дальше? Python? Rust? BrainF*ck?
Это ведь всё те же статически отдаваемые странички... Казалось бы 🤨
gohugo.io
The world's fastest framework for building websites
Hugo is one of the most popular open-source static site generators. With its amazing speed and flexibility, Hugo makes building websites fun again.
😁6
This media is not supported in your browser
VIEW IN TELEGRAM
Рубрика "Век живи, век учись" 🎓
Не первый год работаю на #Linux, но когда нужно вызвать недавнюю команду в консоли, по привычке либо тыкаю стрелку вверх, пока команда не появится, либо пишу что-то типа
Оказывается, это режим, в котором можно начать писать что угодно, и он будет выводить команды из истории, в которых содержался вводимый текст. Листать варианты можно как в обратном порядке (тем же
Как выяснилось, это довольно древняя фича, которая есть практически во всех оболочках (bash, zsh и других). Теперь уже не понимаю, как жил без неё раньше🤓
Не первый год работаю на #Linux, но когда нужно вызвать недавнюю команду в консоли, по привычке либо тыкаю стрелку вверх, пока команда не появится, либо пишу что-то типа
history | grep <что-то>. А тут на днях случайно нажал в консоли Ctrl+R (думал, что нахожусь в браузере) и увидел странное сообщение reverse-i-search. Стал гуглить, что это такое, и ахнул 🤩Оказывается, это режим, в котором можно начать писать что угодно, и он будет выводить команды из истории, в которых содержался вводимый текст. Листать варианты можно как в обратном порядке (тем же
Ctrl+R), так и в прямом (Ctrl+S). Когда команда найдена, остается только жмакнуть Tab либо Enter, в зависимости от того, нужно её поправить перед выполнением или нет ▶️Как выяснилось, это довольно древняя фича, которая есть практически во всех оболочках (bash, zsh и других). Теперь уже не понимаю, как жил без неё раньше🤓
👍14🔥4
Сегодняшнее рабочее утро началось с необходимости повторной аутентификации в Telegram на всех устройствах, причем где-то двух-факторной, а где-то и трёх (даже не знал, что здесь такое бывает)🥴
Вторым неприятным сюрпризом оказалась заморозка аккаунта моего Telegram-бота для поиска своих фотографий в больших альбомах (про него здесь был отдельный пост). При этом ни @SpamBot, ни @BotFather ничего о заморозке не сообщают, равно как и не было сервисных уведомлений от самого Telegram 🤷♂️
Поэтому в качестве оперативной меры бот перезапущен под новым ником: @FramePhotoAlbumBot 🤖
Если кто-то в курсе, что происходит, расскажите, пожалуйста 👀
Вторым неприятным сюрпризом оказалась заморозка аккаунта моего Telegram-бота для поиска своих фотографий в больших альбомах (про него здесь был отдельный пост). При этом ни @SpamBot, ни @BotFather ничего о заморозке не сообщают, равно как и не было сервисных уведомлений от самого Telegram 🤷♂️
Поэтому в качестве оперативной меры бот перезапущен под новым ником: @FramePhotoAlbumBot 🤖
Если кто-то в курсе, что происходит, расскажите, пожалуйста 👀
Telegram
Верхняя полка📝
Давно обещал рассказать вам об очередной программной поделке, идеей которой загорелся ещё в конце прошлого года — Telegram-бот для поиска своих фоток в больших открытых альбомах 👨💻
Мотивация проста:
— я часто участвую в массовых мероприятиях, где работают…
Мотивация проста:
— я часто участвую в массовых мероприятиях, где работают…
🤔8😱2
Кастомные JFR события в дикой природе 🦒
На моем тренинге по #JFR мы с участниками, кроме прочего, учимся делать собственные JFR события, чтобы эммитить их прямо из бизнес-логики, а потом анализировать так же, как встроенные события JVM. И хотя я стараюсь объяснять, зачем это надо, в воздухе нередко остаётся висеть незаданный вопрос участников: "А зачем бы я применил(а) это у себя в проекте?" 🧐
Делюсь свежим примером из своей практики 👇
Когда-то я рассказывал вам, что мы пилим свой условный аналог Excel на платформе AggreGate. Сейчас на этом решении наш партнёр реализует огромный проект для заказчика, и движок вычислений там используется в полный рост, потому что хотелки у заказчика тоже не слабые:
— десятки больших таблиц
— сотни тысяч ячеек в них
— ≈280К узлов в графе связей между ячейками разных таблиц 🕸
Ну и конечно же на этом фоне к нам в JIRA стали периодически поступать тикеты с интригующими заголовками в духе: "У нас где-то что-то когда-то почему-то не посчиталось/не обновилось/не сбросилось, но мы не поняли, где, когда и почему. Разбирайтесь😘"
Как вы наверняка догадываетесь, логировать вычисления в таких масштабах, а потом купаться в этих логах (или выгружать их в какой-то парсер-анализатор) — затея трудоёмкая и малоперспективная. Но видеть ход вычислений в точности до ячеек всё же надо. То есть нужен максимально простой, дешевый (с т.з. overhead'а) и пригодный для анализа результатов способ как-то фиксировать вычисления ✍️
И тут я снова вспомнил про кастомные события JFR, ведь у них очень простой, но при этом гибкий API, они весьма дешевы в эмиссии и хранении, а их анализ в Java Mission Control хоть и не так мощен, как какой-нибудь Logstash+Kibana, но всё же на порядок удобнее, чем с логами 🧶
Я завёл класс с описанием вычисления (см. скриншот 1) и стал эмитить с ним JFR события в двух местах:
— при инициации вычислений (на пользовательском вводе или открытии готовой таблицы)
— и при обновлении по слушателю (когда пересчёт одной ячейки аффектит другую).
Это позволило регистрировать 100% вычислений 💯
Зная масштабы проекта, я опасался, что JFR записи будут огромными и с ними будет тяжело работать, поэтому воспользовался фичей JFR API по добавлению кастомных настроек — поддержал фильтрацию регистрируемых вычислений по диапазону ячеек в обычной нотации Excel, например,
Любопытно, что изначально я планировал управлять этой диагностикой через утилиту
Теперь мы этим активно пользуемся, и когда приносят очередную задачу по проблеме вычислений, знаем, с чего начинать анализ 🕵️♂️
Конечно, сама по себе диагностика на JFR-событиях сложные/редкие/заковыристые проблемы не решает. Но она прокладывает очень важный и довольно длинный кусочек мостика между "Черт возьми, что здесь вообще происходит!?" и статусом тикета "Resolved (Fixed)" ✅
На моем тренинге по #JFR мы с участниками, кроме прочего, учимся делать собственные JFR события, чтобы эммитить их прямо из бизнес-логики, а потом анализировать так же, как встроенные события JVM. И хотя я стараюсь объяснять, зачем это надо, в воздухе нередко остаётся висеть незаданный вопрос участников: "А зачем бы я применил(а) это у себя в проекте?" 🧐
Делюсь свежим примером из своей практики 👇
Когда-то я рассказывал вам, что мы пилим свой условный аналог Excel на платформе AggreGate. Сейчас на этом решении наш партнёр реализует огромный проект для заказчика, и движок вычислений там используется в полный рост, потому что хотелки у заказчика тоже не слабые:
— десятки больших таблиц
— сотни тысяч ячеек в них
— ≈280К узлов в графе связей между ячейками разных таблиц 🕸
Ну и конечно же на этом фоне к нам в JIRA стали периодически поступать тикеты с интригующими заголовками в духе: "У нас где-то что-то когда-то почему-то не посчиталось/не обновилось/не сбросилось, но мы не поняли, где, когда и почему. Разбирайтесь😘"
Как вы наверняка догадываетесь, логировать вычисления в таких масштабах, а потом купаться в этих логах (или выгружать их в какой-то парсер-анализатор) — затея трудоёмкая и малоперспективная. Но видеть ход вычислений в точности до ячеек всё же надо. То есть нужен максимально простой, дешевый (с т.з. overhead'а) и пригодный для анализа результатов способ как-то фиксировать вычисления ✍️
И тут я снова вспомнил про кастомные события JFR, ведь у них очень простой, но при этом гибкий API, они весьма дешевы в эмиссии и хранении, а их анализ в Java Mission Control хоть и не так мощен, как какой-нибудь Logstash+Kibana, но всё же на порядок удобнее, чем с логами 🧶
Я завёл класс с описанием вычисления (см. скриншот 1) и стал эмитить с ним JFR события в двух местах:
— при инициации вычислений (на пользовательском вводе или открытии готовой таблицы)
— и при обновлении по слушателю (когда пересчёт одной ячейки аффектит другую).
Это позволило регистрировать 100% вычислений 💯
Зная масштабы проекта, я опасался, что JFR записи будут огромными и с ними будет тяжело работать, поэтому воспользовался фичей JFR API по добавлению кастомных настроек — поддержал фильтрацию регистрируемых вычислений по диапазону ячеек в обычной нотации Excel, например,
sheet_a!B5:F16 (скриншот 2). Но моему к приятному удивлению, это оказалось лишним: недавно коллеги по запарке оставили JFR-запись включенной без этого фильтра на 21 час, и в неё набежало 303 000 событий, а получившийся JFR файл весил 105 МБ. При этом он без труда открылся в JMC, а работать с ним было также легко, как и с маленьким (скриншот 3) 🌿Любопытно, что изначально я планировал управлять этой диагностикой через утилиту
jattach, но в закрытый контур заказчика втащить даже безобидную jattach оказалось нельзя (небезопасно типа). Тогда мне пришлось извернуться и написать на платформенном low-code-языке функции, которые через JFR API дёргают методы запуска/останова записи, да еще и конфигурируют нужные события. Как ни странно, функции получились довольно компактными и сработали чётко, а в качестве бонуса их вызов удалось вывести прямо в UI-интерфейс платформы для удобства администраторов 👷🏼Теперь мы этим активно пользуемся, и когда приносят очередную задачу по проблеме вычислений, знаем, с чего начинать анализ 🕵️♂️
Конечно, сама по себе диагностика на JFR-событиях сложные/редкие/заковыристые проблемы не решает. Но она прокладывает очень важный и довольно длинный кусочек мостика между "Черт возьми, что здесь вообще происходит!?" и статусом тикета "Resolved (Fixed)" ✅
👍9🔥1