Приведу несколько типичных ошибок.
Типичная ошибка, игнорирование обратной связи вообще. “У нас же монга с кафкой, они всё выдержат”. Нет, не выдержат. Рано или поздно нагрузка превысит возможности, и система упадёт. Обратная связь не опциональная фича для highload-систем. Это необходимость для любой системы, которая хочет выжить.
Другая ошибка, неправильная настройка. Rate limit на 1000 запросов в секунду, когда система реально может обработать только 100. Или circuit breaker, который срабатывает после одной ошибки и блокирует сервис на час. Или кеш с TTL в секунду, который не даёт никакого эффекта. Обратная связь должна быть настроена под реальные возможности системы и требования бизнеса. Иначе она либо не поможет, либо навредит.
Третья ошибка, отсутствие мониторинга. Если ты не видишь, когда и как срабатывает обратная связь, ты не можешь понять, работает ли она правильно. Сколько запросов отклоняется rate limiterом? Как часто circuit breaker банит ресурс? Насколько часто пользователи видят устаревшие данные из кеша? Какой вообще hit rate по кешу? Без метрик обратная связь становится чёрным ящиком, и ты не знаешь, помогает она или мешает.
Четвёртая ошибка, обратная связь только на одном уровне. Защитил вход rate limiterом, но забыл про чтение. Или настроил кеширование, но не подумал про фоновые задачи. Система всё равно падает, просто в другом месте. Нужна комплексная система обратных связей, которая покрывает все уровни архитектуры.
Типичная ошибка, игнорирование обратной связи вообще. “У нас же монга с кафкой, они всё выдержат”. Нет, не выдержат. Рано или поздно нагрузка превысит возможности, и система упадёт. Обратная связь не опциональная фича для highload-систем. Это необходимость для любой системы, которая хочет выжить.
Другая ошибка, неправильная настройка. Rate limit на 1000 запросов в секунду, когда система реально может обработать только 100. Или circuit breaker, который срабатывает после одной ошибки и блокирует сервис на час. Или кеш с TTL в секунду, который не даёт никакого эффекта. Обратная связь должна быть настроена под реальные возможности системы и требования бизнеса. Иначе она либо не поможет, либо навредит.
Третья ошибка, отсутствие мониторинга. Если ты не видишь, когда и как срабатывает обратная связь, ты не можешь понять, работает ли она правильно. Сколько запросов отклоняется rate limiterом? Как часто circuit breaker банит ресурс? Насколько часто пользователи видят устаревшие данные из кеша? Какой вообще hit rate по кешу? Без метрик обратная связь становится чёрным ящиком, и ты не знаешь, помогает она или мешает.
Четвёртая ошибка, обратная связь только на одном уровне. Защитил вход rate limiterом, но забыл про чтение. Или настроил кеширование, но не подумал про фоновые задачи. Система всё равно падает, просто в другом месте. Нужна комплексная система обратных связей, которая покрывает все уровни архитектуры.
❤3
Что в итоге?
Обратная связь очень полезная и нужная штука. Это практический механизм, без которого система не может адаптироваться к изменениям и выживать.
Без обратной связи система работает ровно до первого неожиданного события: пик нагрузки, сбой компонента, изменение требований и всё ломается. С обратной связью система может реагировать, адаптироваться, деградировать управляемо, но продолжать работать.
Мы уже прошли путь от сбора требований через понимание компромиссов и потоков данных к обратной связи. Это логичная последовательность: сначала понимаешь, что нужно системе, потом выбираешь компромиссы, потом видишь, как данные движутся, и, наконец, настраиваешь реакцию системы на изменения.
Обратная связь связывает всё вместе. Она превращает статичную схему в живую систему, которая может реагировать на реальность. Без неё даже самая красивая архитектура останется просто набором компонентов, которые красиво выглядят на диаграмме, но не работают в проде.
Поэтому когда проектируешь систему, думай не только про компоненты и связи между ними. Думай про то, как система будет реагировать, когда что-то пойдёт не так. Потому что что-то обязательно пойдёт не так. И лучше быть к этому готовым.
Простая система с правильной обратной связью лучше сложной системы без неё. Потому что первая продолжит работать, когда вторая упадёт.
И в этом вся суть system design: не нарисовать красивую схему, а построить систему, которая выживет.
Увидимся в Новом году. Кушайте салатики и читайте книги. Хейтеры, люблю вас!
Что ещё почитать:
- 0. System design – это тебе не квадратики рисовать
- 3. System design. Потоки …, гхм, данных - предыдущая статья про потоки
- Release It! Майкл Найгард про проектирование production-ready систем
- The Circuit Breaker Pattern Фаулер про circuit breakers
Обратная связь очень полезная и нужная штука. Это практический механизм, без которого система не может адаптироваться к изменениям и выживать.
Без обратной связи система работает ровно до первого неожиданного события: пик нагрузки, сбой компонента, изменение требований и всё ломается. С обратной связью система может реагировать, адаптироваться, деградировать управляемо, но продолжать работать.
Мы уже прошли путь от сбора требований через понимание компромиссов и потоков данных к обратной связи. Это логичная последовательность: сначала понимаешь, что нужно системе, потом выбираешь компромиссы, потом видишь, как данные движутся, и, наконец, настраиваешь реакцию системы на изменения.
Обратная связь связывает всё вместе. Она превращает статичную схему в живую систему, которая может реагировать на реальность. Без неё даже самая красивая архитектура останется просто набором компонентов, которые красиво выглядят на диаграмме, но не работают в проде.
Поэтому когда проектируешь систему, думай не только про компоненты и связи между ними. Думай про то, как система будет реагировать, когда что-то пойдёт не так. Потому что что-то обязательно пойдёт не так. И лучше быть к этому готовым.
Простая система с правильной обратной связью лучше сложной системы без неё. Потому что первая продолжит работать, когда вторая упадёт.
И в этом вся суть system design: не нарисовать красивую схему, а построить систему, которая выживет.
Увидимся в Новом году. Кушайте салатики и читайте книги. Хейтеры, люблю вас!
Что ещё почитать:
- 0. System design – это тебе не квадратики рисовать
- 3. System design. Потоки …, гхм, данных - предыдущая статья про потоки
- Release It! Майкл Найгард про проектирование production-ready систем
- The Circuit Breaker Pattern Фаулер про circuit breakers
❤4👍1
5. System design. Забиваем гвозди микроскопом
Надеюсь ты, читатель, выжил и с пользой провёл этот новогодний фриз. Тонны салатов, вкусной еды и тотального разложения продуктивности не смогли сломить твою тягу к знаниям и развитию.
С учётом пройденного пути кажется, что всё готово. Требования выбиты, потоки данных распутаны, компромиссы между надёжностью, масштабируемостью и сопровождаемостью найдены, обратная связь продумана. В голове — стройная архитектурная концепция. Пора бы уже и код писать.
Вот он, тот самый момент, которого все мы так ждали. Выбор инструментов. Тех самых квадратиков, которые ты будешь рисовать на схеме.
Рука так и тянется к модному, к «стандартам индустрии». Хочется взять Kafka, потому что «все большие так делают». Запустить десяток микросервисов на Go. Запихнуть всё в Kubernetes и поставить сверху service mesh. А базу, конечно, ту самую очередную Distributed SQL, про которую читал на Хабре.
Астанавись. Выбор инструментов это не награда за проделанную работу. Это не «финальный босс», которого нужно победить эпической убервафлей. Это ещё одна серия компромиссов, где твоим главным врагом становится хайп, а союзником скучный, нудный документ с требованиями.
Почему «просто взять лучшее» не работает?
Потому что у каждого инструмента есть своя цена. И речь не только о лицензии.
Цена обучения. Команда знает PostgreSQL как свои пять пальцев, но ты хочешь CockroachDB для глобального шардинга. Готовы ли всё на месяцы замедлиться, изучая новые паттерны, отладку и тонкости?
Цена эксплуатации. Этот блестящий распределённый кеш самовосстанавливаться при отказе двух узлов? Здорово. А кто будет его мониторить, настраивать и разбираться, почему он вдруг начал терять 1% записей? Это твои SRE? Они уже согласны?
Цена связности. Каждый новый «квадратик» не просто функция. Это новая точка отказа, новый протокол, новый клиент в коде, новый драйвер, новый источник задержек в сетевых вызовах. Микросервис на Rust может быть быстрым, но если для связи с ним всем остальным сервисам нужна кастомная бинарная сериализация, ты добавляешь сложность во всю систему.
Цена моды. Инструмент, о котором все кричат сегодня, завтра может оказаться «legacy-технологией, от которой все уходят». Выбирая его, ты берёшь на себя обязательство по его миграции через N лет.
Надеюсь ты, читатель, выжил и с пользой провёл этот новогодний фриз. Тонны салатов, вкусной еды и тотального разложения продуктивности не смогли сломить твою тягу к знаниям и развитию.
С учётом пройденного пути кажется, что всё готово. Требования выбиты, потоки данных распутаны, компромиссы между надёжностью, масштабируемостью и сопровождаемостью найдены, обратная связь продумана. В голове — стройная архитектурная концепция. Пора бы уже и код писать.
Вот он, тот самый момент, которого все мы так ждали. Выбор инструментов. Тех самых квадратиков, которые ты будешь рисовать на схеме.
Рука так и тянется к модному, к «стандартам индустрии». Хочется взять Kafka, потому что «все большие так делают». Запустить десяток микросервисов на Go. Запихнуть всё в Kubernetes и поставить сверху service mesh. А базу, конечно, ту самую очередную Distributed SQL, про которую читал на Хабре.
Астанавись. Выбор инструментов это не награда за проделанную работу. Это не «финальный босс», которого нужно победить эпической убервафлей. Это ещё одна серия компромиссов, где твоим главным врагом становится хайп, а союзником скучный, нудный документ с требованиями.
Почему «просто взять лучшее» не работает?
Потому что у каждого инструмента есть своя цена. И речь не только о лицензии.
Цена обучения. Команда знает PostgreSQL как свои пять пальцев, но ты хочешь CockroachDB для глобального шардинга. Готовы ли всё на месяцы замедлиться, изучая новые паттерны, отладку и тонкости?
Цена эксплуатации. Этот блестящий распределённый кеш самовосстанавливаться при отказе двух узлов? Здорово. А кто будет его мониторить, настраивать и разбираться, почему он вдруг начал терять 1% записей? Это твои SRE? Они уже согласны?
Цена связности. Каждый новый «квадратик» не просто функция. Это новая точка отказа, новый протокол, новый клиент в коде, новый драйвер, новый источник задержек в сетевых вызовах. Микросервис на Rust может быть быстрым, но если для связи с ним всем остальным сервисам нужна кастомная бинарная сериализация, ты добавляешь сложность во всю систему.
Цена моды. Инструмент, о котором все кричат сегодня, завтра может оказаться «legacy-технологией, от которой все уходят». Выбирая его, ты берёшь на себя обязательство по его миграции через N лет.
🔥2
Так, как же выбирать то?
Отталкивайся не от хайпа, а от следствия.
Твоя отправная точка не список «крутых технологий», смотри на:
Требования из твоего документа. Нужна строгая консистентность? Забудь про eventual consistency stores для записи ядра. Нужны джойны сложных агрегатов? Привет, реляционные базы или тщательно спроектированные документные.
Характеристики потоков данных. Данные пишутся редко, а читаются всегда? Кеш, или read-реплики. Нужна гарантированная доставка событий между контурами? Пора смотреть на брокеры (прости господи). Но не «воткнём Кафку», а «нам нужен персистентный лог с консьюмер-группами».
Выбранные компромиссы. Пожертвовали скоростью записи ради надёжности? Инструмент должен давать сильные гарантии durability. Пожертвовали консистентностью ради масштабируемости? Ищите базу с tuneable consistency.
Пример: Выбираем хранилище для «ленты как у Threads».
Из требований помнишь: скорость чтения критична, актуальность лайков/комментариев может отставать на 5 секунд, рост медленный.
Искушение:
Взять Cassandra или ScyllaDB. Горизонтальное масштабирование, высокая доступность, запись быстрая. Вайбово, надо брать!
Реальность:
Модель данных: лента для каждого пользователя, которая часто пересчитывается. Это запросы по ключу (user_id) с range scan по времени. Cassandra неэффективна для range scans в рамках одного партишна. А денормализовать ленту для каждого подписчика это гигантский объём данных при малом росте.
Скучное решение:
PostgreSQL с таблицей feeds (user_id, post_id, timestamp), правильными индексами и репликой для чтения. На старте выдержит легко. Команда знает. При росте сначала тюнинг, потом партициирование, и только потом, возможно, шардинг. Инструмент соответствует реальным, а не гипотетическим потокам данных.
Критерии выбора: чек-лист перед тем, как «воткнуть»
1. Решает ли он КОНКРЕТНУЮ проблему из моего дизайна? Не «как бы нам использовать Redis», а «нам нужно хранить сессию пользователя с TTL 15 минут».
2. Соответствует ли он «бюджету боли» по сопровождению? Есть ли в команде экспертиза? Есть ли готовые Terraform-модули, Helm-чарты, дашборды в Grafana?
3. Что происходит при его отказе? Это SPOF? Как он интегрируется в нашу обратную связь (circuit breakers, fallbacks)?
4. Как он себя ведёт в наших паттернах доступа? Под нагрузкой, в наших хвостах распределения (p99, p999)?
5. Насколько он нас загоняет в угол? Легко ли будет заменить его через год, если требования изменятся кардинально?
Отталкивайся не от хайпа, а от следствия.
Твоя отправная точка не список «крутых технологий», смотри на:
Требования из твоего документа. Нужна строгая консистентность? Забудь про eventual consistency stores для записи ядра. Нужны джойны сложных агрегатов? Привет, реляционные базы или тщательно спроектированные документные.
Характеристики потоков данных. Данные пишутся редко, а читаются всегда? Кеш, или read-реплики. Нужна гарантированная доставка событий между контурами? Пора смотреть на брокеры (прости господи). Но не «воткнём Кафку», а «нам нужен персистентный лог с консьюмер-группами».
Выбранные компромиссы. Пожертвовали скоростью записи ради надёжности? Инструмент должен давать сильные гарантии durability. Пожертвовали консистентностью ради масштабируемости? Ищите базу с tuneable consistency.
Пример: Выбираем хранилище для «ленты как у Threads».
Из требований помнишь: скорость чтения критична, актуальность лайков/комментариев может отставать на 5 секунд, рост медленный.
Искушение:
Взять Cassandra или ScyllaDB. Горизонтальное масштабирование, высокая доступность, запись быстрая. Вайбово, надо брать!
Реальность:
Модель данных: лента для каждого пользователя, которая часто пересчитывается. Это запросы по ключу (user_id) с range scan по времени. Cassandra неэффективна для range scans в рамках одного партишна. А денормализовать ленту для каждого подписчика это гигантский объём данных при малом росте.
Скучное решение:
PostgreSQL с таблицей feeds (user_id, post_id, timestamp), правильными индексами и репликой для чтения. На старте выдержит легко. Команда знает. При росте сначала тюнинг, потом партициирование, и только потом, возможно, шардинг. Инструмент соответствует реальным, а не гипотетическим потокам данных.
Критерии выбора: чек-лист перед тем, как «воткнуть»
1. Решает ли он КОНКРЕТНУЮ проблему из моего дизайна? Не «как бы нам использовать Redis», а «нам нужно хранить сессию пользователя с TTL 15 минут».
2. Соответствует ли он «бюджету боли» по сопровождению? Есть ли в команде экспертиза? Есть ли готовые Terraform-модули, Helm-чарты, дашборды в Grafana?
3. Что происходит при его отказе? Это SPOF? Как он интегрируется в нашу обратную связь (circuit breakers, fallbacks)?
4. Как он себя ведёт в наших паттернах доступа? Под нагрузкой, в наших хвостах распределения (p99, p999)?
5. Насколько он нас загоняет в угол? Легко ли будет заменить его через год, если требования изменятся кардинально?
🔥3
Что в итоге?
Сначала: принципиальное решение (например, «нам нужен персистентный лог событий»).
Потом: варианты (Kafka, NATS JetStream, Pulsar, RabbitMQ с quorum queues).
Затем: проверка по чек-листу против ТВОИХ требований и контекста (нагрузка, экспертиза, инфраструктура).
В финале: конкретный инструмент.
Правильно выбранный инструмент тот, что тихо растворяется в архитектуре, позволяя системе работать так, как ты задумал. Не тот, что требует к себе постоянного внимания и героических усилий.
Архитектура рождается из требований и компромиссов, а не из списка технологий. Инструмент это всего лишь наиболее точная реализация твоего решения на данном этапе. Лучше взять простое и знакомое решение. Это лучше, чем выбирать модное без понимания, зачем.
А что дальше? Дальше код, деплой, метрики и... встреча с суровой реальностью. А почему это ещё не конец, я расскажу в следующий раз.
Читайте книги, пишите код, кушайте кашу.
Что ещё почитать:
- Database of Databases — поможет с выбором бд
- Martin Fowler — Technology Radar — хороший источник для размышлений о зрелости технологий.
- 4. System design. Обратная связь. Если бы мы знали, что это такое, но мы не знаем, что это такое
Сначала: принципиальное решение (например, «нам нужен персистентный лог событий»).
Потом: варианты (Kafka, NATS JetStream, Pulsar, RabbitMQ с quorum queues).
Затем: проверка по чек-листу против ТВОИХ требований и контекста (нагрузка, экспертиза, инфраструктура).
В финале: конкретный инструмент.
Правильно выбранный инструмент тот, что тихо растворяется в архитектуре, позволяя системе работать так, как ты задумал. Не тот, что требует к себе постоянного внимания и героических усилий.
Архитектура рождается из требований и компромиссов, а не из списка технологий. Инструмент это всего лишь наиболее точная реализация твоего решения на данном этапе. Лучше взять простое и знакомое решение. Это лучше, чем выбирать модное без понимания, зачем.
А что дальше? Дальше код, деплой, метрики и... встреча с суровой реальностью. А почему это ещё не конец, я расскажу в следующий раз.
Читайте книги, пишите код, кушайте кашу.
Что ещё почитать:
- Database of Databases — поможет с выбором бд
- Martin Fowler — Technology Radar — хороший источник для размышлений о зрелости технологий.
- 4. System design. Обратная связь. Если бы мы знали, что это такое, но мы не знаем, что это такое
🔥5
06. System design. А где конец то?
Всё хорошее и плохое имеет свойство заканчиваться, и я спешу тебя порадовать: мы с тобой добрались до финальной части серии про System Design. Путь был сложный, много буков было написано. Я последовательно попытался донести ключевые моменты о процессе проектирования архитектуры.
Надеюсь, сейчас ты уже понимаешь, что архитектура — это далеко не просто красивая схема. Это длительный и сложный итеративный процесс сбора требований. Это глубокий анализ и понимание потоков данных. Это кропотливое планирование обратной связи. И, наконец, это трезвый выбор инструментов без погони за «стандартом индустрии». Всё это вместе помогает создать архитектуру, способную выжить в проде.
Примерно на этом этапе принципиальная схема с детализацией для разных команд и специалистов готова, ТЗ написано, спецификации составлены, и таргеты определены. Команды окончательно определились с инструментами и подходами к реализации, начинают писать код и собирать инфру.
Казалось бы, всё, конец. Можно спокойно выдохнуть, дождаться альфы, посмотреть, как это всё будет дышать в приближённой к реальности среде.
Но нет. К сожалению, а может, и счастью, это далеко не конец. А почему? С какого?
Всё хорошее и плохое имеет свойство заканчиваться, и я спешу тебя порадовать: мы с тобой добрались до финальной части серии про System Design. Путь был сложный, много буков было написано. Я последовательно попытался донести ключевые моменты о процессе проектирования архитектуры.
Надеюсь, сейчас ты уже понимаешь, что архитектура — это далеко не просто красивая схема. Это длительный и сложный итеративный процесс сбора требований. Это глубокий анализ и понимание потоков данных. Это кропотливое планирование обратной связи. И, наконец, это трезвый выбор инструментов без погони за «стандартом индустрии». Всё это вместе помогает создать архитектуру, способную выжить в проде.
Примерно на этом этапе принципиальная схема с детализацией для разных команд и специалистов готова, ТЗ написано, спецификации составлены, и таргеты определены. Команды окончательно определились с инструментами и подходами к реализации, начинают писать код и собирать инфру.
Казалось бы, всё, конец. Можно спокойно выдохнуть, дождаться альфы, посмотреть, как это всё будет дышать в приближённой к реальности среде.
Но нет. К сожалению, а может, и счастью, это далеко не конец. А почему? С какого?
❤1
У самурая есть только путь
И у архитектуры тоже. Тот момент, когда код написан, а инфраструктура поднята, далеко не финишная черта. Это лишь первый серьёзный контрольный пункт на бесконечной трассе. Потому что живая система не может быть статичной. Она дышит, меняется, сталкивается с реальностью.
Ты помнишь три столпа: надёжность, масштабируемость и сопровождаемость? Так вот, прод — это полигон, где они вступают в жестокую схватку. Твоя архитектурная схема превращается в реальность, и эта реальность начинает ставить эксперименты:
Теория потоков данных сталкивается с практикой. Ты разделил read-path, write-path и обработку. Отлично. Но теперь метрики показывают, что твой "изолированный" контур обработки в фоне неожиданно конкурирует за дисковый IO с репликацией базы в пиковое время. Поток данных оказался хитрее твоей схемы. Значит, надо корректировать: менять расписание, добавлять лимиты, пересматривать приоритеты.
Обратная связь проходит боевое крещение. Ты настроил Circuit Breaker и backpressure. А они срабатывают слишком часто или, наоборот, молчат, когда уже всё прилегло. Приходится калибровать пороги по живому трафику. Твои "управляемая деградация" и "предсказуемый отказ" из красивых слов превращаются в конкретные скрипты, алерты и рутину эксплуатации.
Выбор инструментов проверяется на прочность. Ты не поддался и взял «скучный» PostgreSQL. Он отлично держит. Но оказалось, что одна конкретная аналитическая выборка, о которой забыли спросить на старте, выполняется 20 секунд. Придётся думать: то ли денормализовать, то ли параллелить, то ли подружить его с тем самым ClickHouse, против которого ты выступал.
Компромиссы перестают быть абстрактными. Ты решил пожертвовать строгой консистентностью ради скорости. И вот первый пользователь пишет в саппорт: "Я только что лайкнул пост, а счётчик не обновился!". Бизнес задаёт вопрос: "Это баг или фича?". Тебе приходится объяснять, что это не баг, а осознанный выбор, и договариваться, как сделать эту "фичу" менее болезненной для пользователя.
Это и есть тот самый путь. Архитектура — это не проект, который можно сдать. Это состояние системы и процесса вокруг неё.
И у архитектуры тоже. Тот момент, когда код написан, а инфраструктура поднята, далеко не финишная черта. Это лишь первый серьёзный контрольный пункт на бесконечной трассе. Потому что живая система не может быть статичной. Она дышит, меняется, сталкивается с реальностью.
Ты помнишь три столпа: надёжность, масштабируемость и сопровождаемость? Так вот, прод — это полигон, где они вступают в жестокую схватку. Твоя архитектурная схема превращается в реальность, и эта реальность начинает ставить эксперименты:
Теория потоков данных сталкивается с практикой. Ты разделил read-path, write-path и обработку. Отлично. Но теперь метрики показывают, что твой "изолированный" контур обработки в фоне неожиданно конкурирует за дисковый IO с репликацией базы в пиковое время. Поток данных оказался хитрее твоей схемы. Значит, надо корректировать: менять расписание, добавлять лимиты, пересматривать приоритеты.
Обратная связь проходит боевое крещение. Ты настроил Circuit Breaker и backpressure. А они срабатывают слишком часто или, наоборот, молчат, когда уже всё прилегло. Приходится калибровать пороги по живому трафику. Твои "управляемая деградация" и "предсказуемый отказ" из красивых слов превращаются в конкретные скрипты, алерты и рутину эксплуатации.
Выбор инструментов проверяется на прочность. Ты не поддался и взял «скучный» PostgreSQL. Он отлично держит. Но оказалось, что одна конкретная аналитическая выборка, о которой забыли спросить на старте, выполняется 20 секунд. Придётся думать: то ли денормализовать, то ли параллелить, то ли подружить его с тем самым ClickHouse, против которого ты выступал.
Компромиссы перестают быть абстрактными. Ты решил пожертвовать строгой консистентностью ради скорости. И вот первый пользователь пишет в саппорт: "Я только что лайкнул пост, а счётчик не обновился!". Бизнес задаёт вопрос: "Это баг или фича?". Тебе приходится объяснять, что это не баг, а осознанный выбор, и договариваться, как сделать эту "фичу" менее болезненной для пользователя.
Это и есть тот самый путь. Архитектура — это не проект, который можно сдать. Это состояние системы и процесса вокруг неё.
❤1
Финал? Нет, передача эстафеты
Когда первая версия системы уезжает в прод, твоя роль как проектировщика не заканчивается. Она трансформируется. Теперь ты не столько архитектор-созидатель, сколько архитектор-исследователь и наставник.
Ты передаёшь эстафету командам эксплуатации (SRE/DevOps) и разработки, снабжая их не просто схемой, а моделью мышления:
Карта рисков и слабых мест — показываешь, где система может хрустнуть, и как это заметить по метрикам.
План действий при пожаре — что масштабировать в первую очередь, какие фичи можно отключить, как интерпретировать алерты.
Принципы эволюции — объясняешь, почему нельзя "быстро прикрутить" новую фичу, нарушающую разделение потоков данных, и как это сделать правильно.
А сам возвращаешься к началу цикла. К анализу метрик, к новым требованиям бизнеса, к проектированию следующих итераций. Потому что система, которая не эволюционирует, — мёртвая система.
Так что же, всё напрасно? Вечный цикл «нарисовали-сломали-перерисовали»? Никакого конца?
Как раз наоборот! Вся проделанная работа — сбор требований, осознание компромиссов, проектирование потоков и обратной связи, трезвый выбор инструментов — это и есть тот самый фундамент, карта и компас. Ты не построил неприступную крепость на века. Ты построил живой, адаптивный организм и дал команде инструменты для его развития.
Фундамент — потому что без этой работы система рухнет при первом же столкновении с реальностью.
Карта — потому что теперь ты видишь не просто квадратики, а ландшафт, где текут данные и как система на них реагирует.
Компас — потому что когда появляются новые требования или всё идёт не по плану, у тебя есть принципы (те самые три столпа) и понимание потоков, чтобы принимать решения, а не тыкать пальцем в небо.
Когда первая версия системы уезжает в прод, твоя роль как проектировщика не заканчивается. Она трансформируется. Теперь ты не столько архитектор-созидатель, сколько архитектор-исследователь и наставник.
Ты передаёшь эстафету командам эксплуатации (SRE/DevOps) и разработки, снабжая их не просто схемой, а моделью мышления:
Карта рисков и слабых мест — показываешь, где система может хрустнуть, и как это заметить по метрикам.
План действий при пожаре — что масштабировать в первую очередь, какие фичи можно отключить, как интерпретировать алерты.
Принципы эволюции — объясняешь, почему нельзя "быстро прикрутить" новую фичу, нарушающую разделение потоков данных, и как это сделать правильно.
А сам возвращаешься к началу цикла. К анализу метрик, к новым требованиям бизнеса, к проектированию следующих итераций. Потому что система, которая не эволюционирует, — мёртвая система.
Так что же, всё напрасно? Вечный цикл «нарисовали-сломали-перерисовали»? Никакого конца?
Как раз наоборот! Вся проделанная работа — сбор требований, осознание компромиссов, проектирование потоков и обратной связи, трезвый выбор инструментов — это и есть тот самый фундамент, карта и компас. Ты не построил неприступную крепость на века. Ты построил живой, адаптивный организм и дал команде инструменты для его развития.
Фундамент — потому что без этой работы система рухнет при первом же столкновении с реальностью.
Карта — потому что теперь ты видишь не просто квадратики, а ландшафт, где текут данные и как система на них реагирует.
Компас — потому что когда появляются новые требования или всё идёт не по плану, у тебя есть принципы (те самые три столпа) и понимание потоков, чтобы принимать решения, а не тыкать пальцем в небо.
❤1
Что в итоге?
Ты прошёл полный цикл взрослого System Design:
1. Перестал рисовать квадратики и понял, что дизайн — это борьба с реальностью.
2. Научился задавать неудобные вопросы, чтобы превращать влажные фантазии бизнеса в измеримые требования.
3. Осознал три столпа: надёжность, масштабируемость, сопровождаемость — и начал жонглировать их противоречиями.
4. Увидел систему как потоки данных и разделил их на контуры записи, чтения и обработки.
5. Научил систему реагировать на мир с помощью обратной связи: backpressure, circuit breakers и управляемой деградации.
6. Осознанно выбрал инструменты, не поддавшись искушению забивать гвозди микроскопом.
И вот теперь ты здесь. Понимаешь, что конечной точки нет. Есть только путь постоянной адаптации, рефакторинга и осознанных компромиссов. И в этом — вся красота и сложность.
Главное — не бояться начинать, мыслить структурно и помнить, что лучшая архитектура та, что позволяет системе и команде меняться не ломаясь. А путь, как известно, и есть главная цель.
Спасибо, что прошёл этот путь со мной. Удачи в проектировании систем, которые не просто работают, а живут и растут.
Я не прощаюсь, совсем скоро вернусь и принесу почитать что-нибудь интересное.
Что ещё почитать для пути:
· Книга «Designing Data-Intensive Applications» Мартина Клеппмана — библия по теме.
· Блог High Scalability — разборы архитектур реальных компаний.
· Книга «Release It!» Майкла Найгарда — про то, как проектировать системы, которые не падают в проде.
· Technology Radar от ThoughtWorks — чтобы держать руку на пульсе, но не гнаться за каждой волной.
Ты прошёл полный цикл взрослого System Design:
1. Перестал рисовать квадратики и понял, что дизайн — это борьба с реальностью.
2. Научился задавать неудобные вопросы, чтобы превращать влажные фантазии бизнеса в измеримые требования.
3. Осознал три столпа: надёжность, масштабируемость, сопровождаемость — и начал жонглировать их противоречиями.
4. Увидел систему как потоки данных и разделил их на контуры записи, чтения и обработки.
5. Научил систему реагировать на мир с помощью обратной связи: backpressure, circuit breakers и управляемой деградации.
6. Осознанно выбрал инструменты, не поддавшись искушению забивать гвозди микроскопом.
И вот теперь ты здесь. Понимаешь, что конечной точки нет. Есть только путь постоянной адаптации, рефакторинга и осознанных компромиссов. И в этом — вся красота и сложность.
Главное — не бояться начинать, мыслить структурно и помнить, что лучшая архитектура та, что позволяет системе и команде меняться не ломаясь. А путь, как известно, и есть главная цель.
Спасибо, что прошёл этот путь со мной. Удачи в проектировании систем, которые не просто работают, а живут и растут.
Я не прощаюсь, совсем скоро вернусь и принесу почитать что-нибудь интересное.
Что ещё почитать для пути:
· Книга «Designing Data-Intensive Applications» Мартина Клеппмана — библия по теме.
· Блог High Scalability — разборы архитектур реальных компаний.
· Книга «Release It!» Майкла Найгарда — про то, как проектировать системы, которые не падают в проде.
· Technology Radar от ThoughtWorks — чтобы держать руку на пульсе, но не гнаться за каждой волной.
❤4🔥1
Да, это ещё один инженер с мнением
Ночь, комната, макбук, проекты. За последние несколько лет для меня это стало нормой. Хотя все и говорят, что нельзя вести такой образ жизни. Но для меня в этом всё ещё остаётся некоторая доля романтики. Ближе к ночи, окружение затихает, перестают постоянно писать в мессенджеры, город засыпает. Просыпается мафия, и я.
Ближе к полуночи в обнимку с макбуком и чайником какого-нибудь китайского чая, погружаешься в проект, ловишь поток и пропадаешь из реальности на несколько часов. Отдаёшь себя полностью этим строкам кода, схемам, паттернам, архитектуре. Мне кажется, именно ночью, я находил ключевые решения бизнес задач, которые в последующем приносили мне и компании иксы в прибыли. Именно в это время, как мне кажется, я растил хард скилы, софт скилы, мышление и усталость. Для меня это особенное время. А к чему это я?
Да так, захотелось поделиться, и думаю настало время познакомиться, наконец.
Думаю, ты, читатель, задавался вопросом, что это за хуй, и почему он пытается мне втереть всю эту дичь.
В целом вопрос резонный. Я не хотел бы рассказывать тебе, какой я красивый, умный и вообще пивдатый. Это всё не так, автор априори, туп, глуп, ничего не смыслит в разработке и архитектуре. Но за последние несколько лет я немного понахватался всякого и повидал разного. Построил пару систем, познакомился с ияй, плотненько погрузился в архитектуру и работу в стезе platform инженера.
Я топлю за zero deps подход, наверное, ты уже догадался. Но не только из-за безопасности, нет, это только верхушка. Zero-deps даёт контроль и возможность выжать максимум. Максимальный Performance это то, к чему я стремлюсь. Если что-то сделать можно более эффективно, постараюсь это сделать.
Я много читаю, изучаю архитектуру и паттерны и стараюсь следить за современными тенденциями. Правда, иногда эти тенденции мне очень не нравятся, привет брокерам ака очередям.
Считаю, что, если задачу можно решить просто, быстро и без зависимостей, то так и стоит сделать. Не стоит тащить туда инструменты ради инструментов, особенно если это увеличивает плечо разработки.
Я развлекаюсь тем, что на досуге собираю chromium и electron, делаю патчи для них. Отдыхаю за исследованиями возможностей и границ языка, инструментов.
На данный момент из публичного, это microlike фреймворк поверх uWebSockets, изучаю оверхед, который приносит nodejs и как дорого приходится платить за удобство.
За эти годы мне довелось поработать с довольно разными системами, от высоконагруженных микросервисов на ноде и realtime сервисов до инфраструктуры, протоколов, автоматизации и продуктовых платформ. Возможно, когда-нибудь смогу рассказать подробнее ;)
А ещё у меня есть большой оранжевый джип, любимая жена и кот. Люблю читать фантастику и собирать лего, и как всё играю в компуктерные игры.
Жена, привет, знаю, ты это прочитаешь. Спасибо и тебе, читатель.
Кушайте кашу и читайте книги. Хейтеры, обнял вас.
Ночь, комната, макбук, проекты. За последние несколько лет для меня это стало нормой. Хотя все и говорят, что нельзя вести такой образ жизни. Но для меня в этом всё ещё остаётся некоторая доля романтики. Ближе к ночи, окружение затихает, перестают постоянно писать в мессенджеры, город засыпает. Просыпается мафия, и я.
Ближе к полуночи в обнимку с макбуком и чайником какого-нибудь китайского чая, погружаешься в проект, ловишь поток и пропадаешь из реальности на несколько часов. Отдаёшь себя полностью этим строкам кода, схемам, паттернам, архитектуре. Мне кажется, именно ночью, я находил ключевые решения бизнес задач, которые в последующем приносили мне и компании иксы в прибыли. Именно в это время, как мне кажется, я растил хард скилы, софт скилы, мышление и усталость. Для меня это особенное время. А к чему это я?
Да так, захотелось поделиться, и думаю настало время познакомиться, наконец.
Думаю, ты, читатель, задавался вопросом, что это за хуй, и почему он пытается мне втереть всю эту дичь.
В целом вопрос резонный. Я не хотел бы рассказывать тебе, какой я красивый, умный и вообще пивдатый. Это всё не так, автор априори, туп, глуп, ничего не смыслит в разработке и архитектуре. Но за последние несколько лет я немного понахватался всякого и повидал разного. Построил пару систем, познакомился с ияй, плотненько погрузился в архитектуру и работу в стезе platform инженера.
Я топлю за zero deps подход, наверное, ты уже догадался. Но не только из-за безопасности, нет, это только верхушка. Zero-deps даёт контроль и возможность выжать максимум. Максимальный Performance это то, к чему я стремлюсь. Если что-то сделать можно более эффективно, постараюсь это сделать.
Я много читаю, изучаю архитектуру и паттерны и стараюсь следить за современными тенденциями. Правда, иногда эти тенденции мне очень не нравятся, привет брокерам ака очередям.
Считаю, что, если задачу можно решить просто, быстро и без зависимостей, то так и стоит сделать. Не стоит тащить туда инструменты ради инструментов, особенно если это увеличивает плечо разработки.
Я развлекаюсь тем, что на досуге собираю chromium и electron, делаю патчи для них. Отдыхаю за исследованиями возможностей и границ языка, инструментов.
На данный момент из публичного, это microlike фреймворк поверх uWebSockets, изучаю оверхед, который приносит nodejs и как дорого приходится платить за удобство.
За эти годы мне довелось поработать с довольно разными системами, от высоконагруженных микросервисов на ноде и realtime сервисов до инфраструктуры, протоколов, автоматизации и продуктовых платформ. Возможно, когда-нибудь смогу рассказать подробнее ;)
А ещё у меня есть большой оранжевый джип, любимая жена и кот. Люблю читать фантастику и собирать лего, и как всё играю в компуктерные игры.
Жена, привет, знаю, ты это прочитаешь. Спасибо и тебе, читатель.
Кушайте кашу и читайте книги. Хейтеры, обнял вас.
❤8🔥4
Хреновый ты архитектор, zero deps
Привет, читатель, случилась недавно со мной интересная ситуация.
Пришёл ко мне знакомый, назовём его З, от знакомого Л, и говорит: «zero deps тыж программист, а не сможешь ли ты, мне, пожалуйста, сделать ТГ ботика для учёта моего мелкого бизнеса, за денежку».
Кто я такой, чтобы отказать.
Говорю, не вопрос, любой каприз за ваши деньги, давай подробнее: «Что? Как? Зачем? И почему?»
Обсудили, если коротко: хочется ТГ бот учёта движения деняк в гипермалом бизнесе для самоконтроля. Гугл таблицы надоели, данные «открыты», там не синкается, здесь тормозит, там доступ отвалился. С телефона неудобно, нужен бот.
Бюджет не пилим, сошлись на том, что делаю безвозмездно, а там «спасибо» на усмотрение Товарища З.
Минут 20 покумекал и сложилось ТЗ с примерным планом-капканом и стеком.
План простой: берём термос чая, минут 40 ияй собирает пару визардов и пачку клав на grammy для бота и базовый юзкейс. К этому всему прикручиваем Pg с четырьмя табличками. Тратим часик — полтора на рефакторинг говнокода от ияй — и в продакшен. Живое MVP часа за 3 и термос чая.
Заспичил Товарищу З, сошлись во мнении, что нужно с этим переспать.
Я сплю, а мысль не отпускает: потребность и «хотелку» товарища закроем, а первопричина боли останется. ТГ, имхо, такое себе для учёта. Что-то записать простое и мелкое сойдёт, но чуть большие масштабы не потянет: аналитику, таблички, репорты, и куча всякого ещё будет сложно красиво и удобно нарисовать. Нужна веб-морда.
Накидал ТЗ к веб-морде, сижу, гляжу — вырисовывается excel на минималках без куртизанок и блек-джека. Ясно вижу велосипед на костылях. Но помочь человеку хочется.
Заспичил Товарищу З, снова сошлись на том, что нужно переспать.
Лежу, думаю дальше: зачем так сложно, давай развернём селфхостед. Возьмём какой-нибудь миниайо ака S3 или вообще nextcloud, прикрутим туда onlyoffice как редактор. И получим на выходе свой гуглдиск со своим гуглдоком и гуглщитом. Сотрудникам доступы красивые раздадим, будет учёт «практически excell» с блек-джеком и резиновыми куртизанками.
Проснулся, заспичил Товарищу З селфхостед сверху к боту и веб-морде. Сошлись на том, что нужно переспать. Но веб-морда всё же ближе, а лучше бот, так как не таблицы и бот хочется.
На следующий день поехал к товарищу Л за рюмкой чая, его работу работать.
А товарищ Л, по совместительству, ещё и широко известный в узких кругах крутой техлид, опытный разработчик и человек, который всему меня научил. Мудрый бвана в общем.
Пожаловался ему, поплакался, что вот у меня дилемма: хочется ботика в тг, а можно веб-морду, а ещё можно селфхостед.
И каких же мне в панамку напихали.
Мудрый Бвана сказал простую вещь: архитектор должен решить первопричину боли.
А первопричина боли товарища — в том, что данные «открыты» и «таблички не синкаются».
Тг бот был сразу отвергнут, безапелляционно, залупа.
Разнесена была в пух и прах моя красивая веб-морда: долгое плечо разработки, невозможность без разработчика менять учёт, затраты на впс, домен и жопачасы, поддержка, баги, внедрение. И кто это всё будет тянуть, когда ты на пенсию уйдёшь?
А в финале было предложено сто процентное решение — excel. Да, тот самый, от мелкомягких, с облаком ихейным.
Я тогда со своей панамкой домой уехал, написал Товарищу З, что действительно будет лучше ему в excel погрузиться. А мы с Товарищем Л ему всячески поможем с этим.
Как-то так.
Читайте книги, ищите первопричину боли и кушайте кашу.
P.S. Все персонажи вымышленные. Все совпадения случайны. Все вероятности невероятны.
А Товарищ З себе ботика в итоге навайбкодил за вечер :)
Привет, читатель, случилась недавно со мной интересная ситуация.
Пришёл ко мне знакомый, назовём его З, от знакомого Л, и говорит: «zero deps тыж программист, а не сможешь ли ты, мне, пожалуйста, сделать ТГ ботика для учёта моего мелкого бизнеса, за денежку».
Кто я такой, чтобы отказать.
Говорю, не вопрос, любой каприз за ваши деньги, давай подробнее: «Что? Как? Зачем? И почему?»
Обсудили, если коротко: хочется ТГ бот учёта движения деняк в гипермалом бизнесе для самоконтроля. Гугл таблицы надоели, данные «открыты», там не синкается, здесь тормозит, там доступ отвалился. С телефона неудобно, нужен бот.
Бюджет не пилим, сошлись на том, что делаю безвозмездно, а там «спасибо» на усмотрение Товарища З.
Минут 20 покумекал и сложилось ТЗ с примерным планом-капканом и стеком.
План простой: берём термос чая, минут 40 ияй собирает пару визардов и пачку клав на grammy для бота и базовый юзкейс. К этому всему прикручиваем Pg с четырьмя табличками. Тратим часик — полтора на рефакторинг говнокода от ияй — и в продакшен. Живое MVP часа за 3 и термос чая.
Заспичил Товарищу З, сошлись во мнении, что нужно с этим переспать.
Я сплю, а мысль не отпускает: потребность и «хотелку» товарища закроем, а первопричина боли останется. ТГ, имхо, такое себе для учёта. Что-то записать простое и мелкое сойдёт, но чуть большие масштабы не потянет: аналитику, таблички, репорты, и куча всякого ещё будет сложно красиво и удобно нарисовать. Нужна веб-морда.
Накидал ТЗ к веб-морде, сижу, гляжу — вырисовывается excel на минималках без куртизанок и блек-джека. Ясно вижу велосипед на костылях. Но помочь человеку хочется.
Заспичил Товарищу З, снова сошлись на том, что нужно переспать.
Лежу, думаю дальше: зачем так сложно, давай развернём селфхостед. Возьмём какой-нибудь миниайо ака S3 или вообще nextcloud, прикрутим туда onlyoffice как редактор. И получим на выходе свой гуглдиск со своим гуглдоком и гуглщитом. Сотрудникам доступы красивые раздадим, будет учёт «практически excell» с блек-джеком и резиновыми куртизанками.
Проснулся, заспичил Товарищу З селфхостед сверху к боту и веб-морде. Сошлись на том, что нужно переспать. Но веб-морда всё же ближе, а лучше бот, так как не таблицы и бот хочется.
На следующий день поехал к товарищу Л за рюмкой чая, его работу работать.
А товарищ Л, по совместительству, ещё и широко известный в узких кругах крутой техлид, опытный разработчик и человек, который всему меня научил. Мудрый бвана в общем.
Пожаловался ему, поплакался, что вот у меня дилемма: хочется ботика в тг, а можно веб-морду, а ещё можно селфхостед.
И каких же мне в панамку напихали.
Мудрый Бвана сказал простую вещь: архитектор должен решить первопричину боли.
А первопричина боли товарища — в том, что данные «открыты» и «таблички не синкаются».
Тг бот был сразу отвергнут, безапелляционно, залупа.
Разнесена была в пух и прах моя красивая веб-морда: долгое плечо разработки, невозможность без разработчика менять учёт, затраты на впс, домен и жопачасы, поддержка, баги, внедрение. И кто это всё будет тянуть, когда ты на пенсию уйдёшь?
А в финале было предложено сто процентное решение — excel. Да, тот самый, от мелкомягких, с облаком ихейным.
Я тогда со своей панамкой домой уехал, написал Товарищу З, что действительно будет лучше ему в excel погрузиться. А мы с Товарищем Л ему всячески поможем с этим.
Как-то так.
Читайте книги, ищите первопричину боли и кушайте кашу.
P.S. Все персонажи вымышленные. Все совпадения случайны. Все вероятности невероятны.
А Товарищ З себе ботика в итоге навайбкодил за вечер :)
🔥8
О пользе отдыха для чукчи
Чукча не дурак, чукча иногда пытается отдыхать от этих ваших программирований. Иногда у него это даже получается.
Всё началось не так давно, лет шесть назад. Я молодой и амбициозный, готовый работать за еду, прилетаю в приморский город N. Ничего не предвещало беды, но меня берут на работу в небольшой стартап, обещают кормить, учить и немного деняк. Что, может пойти не так?
В целом всё отлично, я каждый день как штык в офисе, каждый день штудирую learn javascript, воюю на codewars и решаю задачи от мудрых и старших комрадс. Всё бы ничего, но к концу месяца мне говорят, ты себя крут показал, мы тебе заплатим х2, продолжай в том же духе.
И тут понеслась. Мой воспалённый мозг, почему то решил, что если я буду ебашить как чёрт, это будет напрямую конвертироваться в знания, опыт и горы деняк соответственно. В общем то так и получилось. Я просыпался, учился, ехал в офис, учился, кушал в офисе, учился, ехал домой, учился и перед сном тоже учился. День за днём, месяц за месяцем.
Через пару месяцев начались рабочие задачи. Стало ещё интереснее и веселее. Учёба теперь была в перерывах между решением рабочих задач и сном. Рабочие задачи несли ещё больше новых знаний. Я не знал усталости, я не говорил слов: «не знаю», «не получается», «наверное, я не смогу». На все вопросы и предложения я отвечал: «Сейчас узна́ю», «сейчас изучу», «сейчас придумаю решение», «да, конечно, без проблем, сейчас решим». И это давало свои плоды. Знания и опыт ширились, доход стремительно рос, я развивался как специалист. Но было, одно "но".
Этим "но" был отдых. Для меня отдыхом было прочитать пяток статей на тему, как что-то написать, или как что-то работает. Отдыхом для меня были попытки придумать и написать для себя: crm, арбитражного бота, сайтик для бронирования уроков по английскому, бесчисленное количество ботов в тг. Я думал, что отдыхаю, когда изучал, как работает браузер, что за зверь такой этот фингерпринт и зачем его собирают. Думал, что мой мозг переключается при работе не с js, а с плюсами, когда я копался в хроме с электроном. Ой, как я ошибался.
Незаметно для меня пролетели 4 года и пришло оно, выгорание. Ой, ты, читатель, наверное, сейчас начнёшь в меня кидаться говной и кричать, о блет ещё один псевдоразрабочик, типа заебался и выгорел, нытик блет. Ну я в целом тоже так думал. Какое нахер выгорание, тебе ещё 30 нет, ты здоровый молодой, парень, тебе ебашить и ебашить! Ну как бы да, но и не то чтобы нет.
События помимо работы тоже оставляли свой след. Помимо того, что ты ебашишь 24/7, так тебе ещё пиздюлей ментальных, моральных, а иногда ещё и физических старается навесить окружающий мир. Это тоже давало свои плоды. Кукуха решила сказать «Адьес» и ебануть во все стороны, как твой кот, перед тем как сходить посрать.
Ну вот примерно тут я попробовал уйти с текущей работы и плотно заняться собой, здоровьем, кукухой и попробовать отдохнуть. Но и тут, что-то пошло не так. Меня купили, мне предложили неприлично много, и я не смог отказаться. Спасибо моей Жене, которая в тот момент пришла и ультимативно заявила, что хватит это терпеть, тебя тяжело вывозить с твоей кукухой. Ты пиздуешь к психологу, ты ебашишь в зал с тренером и ты, мать твою, делаешь себе хотя бы один выходной в неделю, пидр!
Спасибо тебе, Жена любимая. Ты была права! Я уже полгода замечал за собой, что производительность моя и импакт в работе снизился. Я не мог себя удовлетворить достигнутыми результами при решении задач. Я всё ещё приносил пользу компании, но уже не мог принести пользу себе. И тут чукча сдался.
Чукча не дурак, чукча иногда пытается отдыхать от этих ваших программирований. Иногда у него это даже получается.
Всё началось не так давно, лет шесть назад. Я молодой и амбициозный, готовый работать за еду, прилетаю в приморский город N. Ничего не предвещало беды, но меня берут на работу в небольшой стартап, обещают кормить, учить и немного деняк. Что, может пойти не так?
В целом всё отлично, я каждый день как штык в офисе, каждый день штудирую learn javascript, воюю на codewars и решаю задачи от мудрых и старших комрадс. Всё бы ничего, но к концу месяца мне говорят, ты себя крут показал, мы тебе заплатим х2, продолжай в том же духе.
И тут понеслась. Мой воспалённый мозг, почему то решил, что если я буду ебашить как чёрт, это будет напрямую конвертироваться в знания, опыт и горы деняк соответственно. В общем то так и получилось. Я просыпался, учился, ехал в офис, учился, кушал в офисе, учился, ехал домой, учился и перед сном тоже учился. День за днём, месяц за месяцем.
Через пару месяцев начались рабочие задачи. Стало ещё интереснее и веселее. Учёба теперь была в перерывах между решением рабочих задач и сном. Рабочие задачи несли ещё больше новых знаний. Я не знал усталости, я не говорил слов: «не знаю», «не получается», «наверное, я не смогу». На все вопросы и предложения я отвечал: «Сейчас узна́ю», «сейчас изучу», «сейчас придумаю решение», «да, конечно, без проблем, сейчас решим». И это давало свои плоды. Знания и опыт ширились, доход стремительно рос, я развивался как специалист. Но было, одно "но".
Этим "но" был отдых. Для меня отдыхом было прочитать пяток статей на тему, как что-то написать, или как что-то работает. Отдыхом для меня были попытки придумать и написать для себя: crm, арбитражного бота, сайтик для бронирования уроков по английскому, бесчисленное количество ботов в тг. Я думал, что отдыхаю, когда изучал, как работает браузер, что за зверь такой этот фингерпринт и зачем его собирают. Думал, что мой мозг переключается при работе не с js, а с плюсами, когда я копался в хроме с электроном. Ой, как я ошибался.
Незаметно для меня пролетели 4 года и пришло оно, выгорание. Ой, ты, читатель, наверное, сейчас начнёшь в меня кидаться говной и кричать, о блет ещё один псевдоразрабочик, типа заебался и выгорел, нытик блет. Ну я в целом тоже так думал. Какое нахер выгорание, тебе ещё 30 нет, ты здоровый молодой, парень, тебе ебашить и ебашить! Ну как бы да, но и не то чтобы нет.
События помимо работы тоже оставляли свой след. Помимо того, что ты ебашишь 24/7, так тебе ещё пиздюлей ментальных, моральных, а иногда ещё и физических старается навесить окружающий мир. Это тоже давало свои плоды. Кукуха решила сказать «Адьес» и ебануть во все стороны, как твой кот, перед тем как сходить посрать.
Ну вот примерно тут я попробовал уйти с текущей работы и плотно заняться собой, здоровьем, кукухой и попробовать отдохнуть. Но и тут, что-то пошло не так. Меня купили, мне предложили неприлично много, и я не смог отказаться. Спасибо моей Жене, которая в тот момент пришла и ультимативно заявила, что хватит это терпеть, тебя тяжело вывозить с твоей кукухой. Ты пиздуешь к психологу, ты ебашишь в зал с тренером и ты, мать твою, делаешь себе хотя бы один выходной в неделю, пидр!
Спасибо тебе, Жена любимая. Ты была права! Я уже полгода замечал за собой, что производительность моя и импакт в работе снизился. Я не мог себя удовлетворить достигнутыми результами при решении задач. Я всё ещё приносил пользу компании, но уже не мог принести пользу себе. И тут чукча сдался.
🔥6
Вот уже два года чукча, в лице вашего автора @zerodeps, учится отдыхать. Это оказалось не так-то просто. Это оказалось ппц непросто. Казалось бы, забей хуй, валяйся и читай книгу, ходи по улице или в компьютер поиграй. Но нет, мой коварный мозг постоянно вставляет палки в колёса и пытается навязать мне разные чувства. От мысли, что ты бездарный бездельник, потому что уже 5 минут не проверял рабочий чат, до чувства дичайшего дискомфорта, когда у тебя в грёбаном нигде посреди леса пропадает связь и ты не можешь загрузить чаты в тг. Ещё есть чувство упущенных возможностей, это вообще отдельная тема. Таких примеров я могу привести, наверное, десятки, если не сотни. Возможно, когда-нибудь напишу об этом подробнее.
Два года учусь отдыхать, переключаться и посылать этот мир на хер. Это повышает мой кпд, делает мою работу приятнее. С каждым днём у меня получается отдыхать чуточку лучше. Чего и вам советую ;)
Отдыхайте, кушайте кашу и иногда не читайте книги!
Два года учусь отдыхать, переключаться и посылать этот мир на хер. Это повышает мой кпд, делает мою работу приятнее. С каждым днём у меня получается отдыхать чуточку лучше. Чего и вам советую ;)
Отдыхайте, кушайте кашу и иногда не читайте книги!
🔥5
О том как Чукча свой путь ходит
Буквально каждый человек, который сталкивался с тревогой и всяким таким рядом, слышал о том, что нужно ходить. Да-да, ходить ногами в разные стороны, и это поможет в борьбе с ментальными проблемами и физически полезно. Чукча, @zerodeps, попробовал. И вот как это получилось.
Сразу замечу, что любой вид физической нагрузки может быть полезен, если он в меру. Кто-то ходит в качалочку, кто-то бегает, а кто-то играет в падел — их мы не будем осуждать. Я вот тоже, помимо того, что ходил ходьбу, посещал тренировки с тренером в зале. Стабильно три раза в неделю. Очень было хорошо, пока были на это финансовые возможности. Сейчас могу себе позволить только ходить ногами. Но не будем о грустном, давайте о ходьбе.
Ходьба очень способствует мыслительной деятельности. Машинально переставляя ноги, фокусируешься на работе или пет-проекте, фокусируешься на задаче. Немало решений было мной придумано в зале или во время ходьбы. Наверное, семьдесят процентов материала для блога было написано на дорожке.
Смена деятельности и обстановки — немаловажный фактор. Я обычно хожу дома, на дорожке. Но и в лес иногда выхожу, на улицу. Очень помогает переключиться, отвлечься. Посмотреть на задачу с другой стороны.
Есть ещё момент системный, как бы это ни звучало, но распорядок дня очень помогает держаться на плаву, особенно если в него включена ходьба. Пару месяцев пытаюсь жить по расписанию, у меня это даже получается, и кукухе приятно, и телу. Каждый день стремлюсь начинать одинаково. Проснулся, поплакал, пописал, покушал, походил и за компуктер. И так по кругу, желательно 365 дней в году, с перерывом на выезды на природу. И вам того же желаю.
Как раз подошёл к завершению час ходьбы, спасибо, что читаете.
Как-то так.
Кушайте кашу, ходите и читайте книги
Буквально каждый человек, который сталкивался с тревогой и всяким таким рядом, слышал о том, что нужно ходить. Да-да, ходить ногами в разные стороны, и это поможет в борьбе с ментальными проблемами и физически полезно. Чукча, @zerodeps, попробовал. И вот как это получилось.
Сразу замечу, что любой вид физической нагрузки может быть полезен, если он в меру. Кто-то ходит в качалочку, кто-то бегает, а кто-то играет в падел — их мы не будем осуждать. Я вот тоже, помимо того, что ходил ходьбу, посещал тренировки с тренером в зале. Стабильно три раза в неделю. Очень было хорошо, пока были на это финансовые возможности. Сейчас могу себе позволить только ходить ногами. Но не будем о грустном, давайте о ходьбе.
Ходьба очень способствует мыслительной деятельности. Машинально переставляя ноги, фокусируешься на работе или пет-проекте, фокусируешься на задаче. Немало решений было мной придумано в зале или во время ходьбы. Наверное, семьдесят процентов материала для блога было написано на дорожке.
Смена деятельности и обстановки — немаловажный фактор. Я обычно хожу дома, на дорожке. Но и в лес иногда выхожу, на улицу. Очень помогает переключиться, отвлечься. Посмотреть на задачу с другой стороны.
Есть ещё момент системный, как бы это ни звучало, но распорядок дня очень помогает держаться на плаву, особенно если в него включена ходьба. Пару месяцев пытаюсь жить по расписанию, у меня это даже получается, и кукухе приятно, и телу. Каждый день стремлюсь начинать одинаково. Проснулся, поплакал, пописал, покушал, походил и за компуктер. И так по кругу, желательно 365 дней в году, с перерывом на выезды на природу. И вам того же желаю.
Как раз подошёл к завершению час ходьбы, спасибо, что читаете.
Как-то так.
Кушайте кашу, ходите и читайте книги
👍3🔥2
Объекты в JS не бесплатные
Hidden classes, inline cache и почему shape объекта важнее, чем кажется.
Продолжу про микро-оптимизаций. После
Сразу оговорка: для 99% систем это не имеет значения. А вот если у тебя hot path, через который проходят десятки тысяч объектов в секунду, или ты пишешь библиотечный код, стоит знать, что V8 на самом деле делает с твоими объектами.
И чего он там с ними делает?
Когда ты создаёшь объект, V8 не выделяет «мешок ключей». Он строит для него hidden class (map внутри V8) структуру, которая описывает layout: какие у объекта поля, в каком порядке они лежат, какого типа, по каким офсетам читать. Сам объект это компактный массив значений, как struct в C. Hidden class хранится отдельно, и каждый объект держит на него ссылку.
Hidden classes связаны между собой через transitions и вместе образуют transition tree. Когда ты добавляешь поле к объекту, V8 идёт по исходящему переходу из текущего hidden class: если переход с таким полем уже есть переключается на существующий дочерний, если нет создаёт новый hidden class и новую ветку дерева.
Если несколько объектов идут по одним и тем же переходам в одинаковом порядке они разделяют один hidden class. Это даёт V8 базу для inline cache: «по этому офсету всегда лежит string, читаем напрямую, без проверок».
Когда hidden classes начинают расходиться (по порядку, по типам, по добавлению/удалению), inline cache переходит:
– monomorphic (один shape — fast path),
– polymorphic (до 4 shapes — V8 проверяет каждый, всё ещё быстро),
– megamorphic (4+ — V8 сдаётся, идёт через generic lookup).
Стоимость растёт на каждом шаге.
Где ты теряешь?
Классический пример постепенная сборка vs литерал:
Если порядок добавления полей совпадает, оба варианта в итоге попадают на один hidden class. У литерала есть бонус V8 запоминает финальный shape как boilerplate и при повторных вызовах аллоцирует объект сразу с готовым layout, без прохода по transition tree. Но в hot loop разница в установившемся режиме копеечная.
Хуже, если порядок полей в разных фабриках не совпадает:
Это уже два разных hidden class. Любой код, который читает
Ещё кейс условное добавление полей:
Часть объектов имеет shape
delete — отдельная история
Вот тут V8 уже не прощает.
Вроде как память освободил. А по факту превратил объект в
Если поле больше не нужно лучше присвой
Hidden classes, inline cache и почему shape объекта важнее, чем кажется.
Продолжу про микро-оптимизаций. После
Date.now() и parseInt/parseFloat — про, казалось бы, самую безобидную вещь: обычный {}.Сразу оговорка: для 99% систем это не имеет значения. А вот если у тебя hot path, через который проходят десятки тысяч объектов в секунду, или ты пишешь библиотечный код, стоит знать, что V8 на самом деле делает с твоими объектами.
И чего он там с ними делает?
Когда ты создаёшь объект, V8 не выделяет «мешок ключей». Он строит для него hidden class (map внутри V8) структуру, которая описывает layout: какие у объекта поля, в каком порядке они лежат, какого типа, по каким офсетам читать. Сам объект это компактный массив значений, как struct в C. Hidden class хранится отдельно, и каждый объект держит на него ссылку.
Hidden classes связаны между собой через transitions и вместе образуют transition tree. Когда ты добавляешь поле к объекту, V8 идёт по исходящему переходу из текущего hidden class: если переход с таким полем уже есть переключается на существующий дочерний, если нет создаёт новый hidden class и новую ветку дерева.
Если несколько объектов идут по одним и тем же переходам в одинаковом порядке они разделяют один hidden class. Это даёт V8 базу для inline cache: «по этому офсету всегда лежит string, читаем напрямую, без проверок».
Когда hidden classes начинают расходиться (по порядку, по типам, по добавлению/удалению), inline cache переходит:
– monomorphic (один shape — fast path),
– polymorphic (до 4 shapes — V8 проверяет каждый, всё ещё быстро),
– megamorphic (4+ — V8 сдаётся, идёт через generic lookup).
Стоимость растёт на каждом шаге.
Где ты теряешь?
Классический пример постепенная сборка vs литерал:
const a = {}
a.id = 1
a.name = 'jopa'
const b = { id: 1, name: 'jopa' }
Если порядок добавления полей совпадает, оба варианта в итоге попадают на один hidden class. У литерала есть бонус V8 запоминает финальный shape как boilerplate и при повторных вызовах аллоцирует объект сразу с готовым layout, без прохода по transition tree. Но в hot loop разница в установившемся режиме копеечная.
Хуже, если порядок полей в разных фабриках не совпадает:
function makeA(id, name) { return { id, name } }
function makeB(name, id) { return { name, id } }
Это уже два разных hidden class. Любой код, который читает
obj.id через эти фабрики, видит два shape на одном call site и IC становится polymorphic. Само по себе ещё не больно, но если таких разных объектов не два, а шесть, то добро пожаловать в megamorphic.Ещё кейс условное добавление полей:
const user = { id, name }
if (isAdmin) {
user.role = 'admin'
}
Часть объектов имеет shape
{id, name}, часть — {id, name, role}. Уже polymorphic. Лучше класть role: null сразу и потом присвоить значение при необходимости.delete — отдельная история
delete user.name
Вот тут V8 уже не прощает.
delete переводит объект в dictionary mode (он же slow mode, normalized properties). Это hashmap вместо фиксированного layout. Ни inline cache, ни офсетов, каждое чтение поля идёт через hash lookup в C++ runtime. И обратно V8 объект уже не вернёт, даже если форма стабилизировалась.Вроде как память освободил. А по факту превратил объект в
Map без типизации.Если поле больше не нужно лучше присвой
null или undefined. Shape сохранится, движок не потеряет в оптимизации.🔥3
А что по цифрам?
Стенд: Node 24, миллион объектов с тремя полями, в hot loop читаем
— literal (same shape): 3.99 нс
— stepwise (same order): 4.08 нс
— poly IC (2 shape): 4.65 нс
— megamorphic (6 shapes): 8.51 нс
— dict mode (after `delete`): 56.12 нс
Что видно:
– literal vs stepwise — разницы практически нет. V8 одинаково хорошо справляется с обоими.
– polymorphic IC (2 shape) — ~15% оверхед. V8 спокойно тянет до 4 shape на одном call site.
– megamorphic (6 shape) — x2+ к чтению. Уже серьёзно.
– delete (dictionary mode) — x14 медленнее. Больно :)
На 100k RPS × 50 чтений полей на запрос с dict-mode объектами вместо нормальных — потеря ~260 мс CPU/с.
А что было на Node 22?
Для наглядности — те же сценарии на Node 22:
— literal: 11.0 → 4.0 нс (x2.8)
— stepwise: 11.1 → 4.1 нс (x2.7)
— poly (2 shape): 10.3 → 4.7 нс (x2.2)
— megamorphic: 14.1 → 8.5 нс (x1.7)
— dict mode: 56.8 → 56.1 нс (=)
Что интересно:
– Fast path между релизами стал ~x2.5 быстрее. TurboFan и Maglev продолжают тюниться, монохромное чтение поля на Node 24 — 4 нс против 11 на Node 22.
– Dict mode — константа. 56 нс на обеих версиях. Это C++ hashmap lookup, JIT там не играет, оптимизировать нечего.
– Относительная разница fast/slow растёт. На Node 22
Вывод: с каждым новым V8 сидеть в dictionary mode или megamorphic IC становится всё дороже _относительно_ правильного кода.
А что делать то?
– В hot path — литералы, со всеми полями сразу. Не знаешь значение полож
– Поля во всех фабриках — в одном порядке. Делаешь
–
– Если объект сложный и часто создаётся — класс или фабрика. Один shape гарантированно.
– Не стоит превращать один call site в универсальную точку на все случаи жизни: четыре shape потолок V8, дальше generic.
Что в итоге?
Объект в JS не «просто словарь». Это контракт с V8: ты обещаешь стабильный shape, V8 обещает быструю работу через hidden classes и inline cache. Нарушаешь — съезжаешь в polymorphic, потом megamorphic, потом dictionary mode. С каждым шагом дороже.
В обычном CRUD это не заметно. На hot path — это десятки процентов CPU и заметные хвосты по p99.
Node быстрый. Просто не мешай ему.
Что еще почитать?
– V8 internals: hidden classes & inline caches — Mathias Bynens, must-read
– Fast properties in V8 — официальный блог V8
– Elements kinds in V8 — про массивы и их shapes
Стенд: Node 24, миллион объектов с тремя полями, в hot loop читаем
obj.id, меряем ns/op. По три прогона, чтобы JIT успел устаканиться.— literal (same shape): 3.99 нс
— stepwise (same order): 4.08 нс
— poly IC (2 shape): 4.65 нс
— megamorphic (6 shapes): 8.51 нс
— dict mode (after `delete`): 56.12 нс
Что видно:
– literal vs stepwise — разницы практически нет. V8 одинаково хорошо справляется с обоими.
– polymorphic IC (2 shape) — ~15% оверхед. V8 спокойно тянет до 4 shape на одном call site.
– megamorphic (6 shape) — x2+ к чтению. Уже серьёзно.
– delete (dictionary mode) — x14 медленнее. Больно :)
На 100k RPS × 50 чтений полей на запрос с dict-mode объектами вместо нормальных — потеря ~260 мс CPU/с.
А что было на Node 22?
Для наглядности — те же сценарии на Node 22:
— literal: 11.0 → 4.0 нс (x2.8)
— stepwise: 11.1 → 4.1 нс (x2.7)
— poly (2 shape): 10.3 → 4.7 нс (x2.2)
— megamorphic: 14.1 → 8.5 нс (x1.7)
— dict mode: 56.8 → 56.1 нс (=)
Что интересно:
– Fast path между релизами стал ~x2.5 быстрее. TurboFan и Maglev продолжают тюниться, монохромное чтение поля на Node 24 — 4 нс против 11 на Node 22.
– Dict mode — константа. 56 нс на обеих версиях. Это C++ hashmap lookup, JIT там не играет, оптимизировать нечего.
– Относительная разница fast/slow растёт. На Node 22
delete был x5 медленнее literal'а, на Node 24 — уже x14. Fast path уходит вперёд, slow path стоит.Вывод: с каждым новым V8 сидеть в dictionary mode или megamorphic IC становится всё дороже _относительно_ правильного кода.
А что делать то?
– В hot path — литералы, со всеми полями сразу. Не знаешь значение полож
null.– Поля во всех фабриках — в одном порядке. Делаешь
{ id, name }, делай везде { id, name }.–
delete — не нужон. Только obj.field = null (или undefined).– Если объект сложный и часто создаётся — класс или фабрика. Один shape гарантированно.
– Не стоит превращать один call site в универсальную точку на все случаи жизни: четыре shape потолок V8, дальше generic.
Что в итоге?
Объект в JS не «просто словарь». Это контракт с V8: ты обещаешь стабильный shape, V8 обещает быструю работу через hidden classes и inline cache. Нарушаешь — съезжаешь в polymorphic, потом megamorphic, потом dictionary mode. С каждым шагом дороже.
В обычном CRUD это не заметно. На hot path — это десятки процентов CPU и заметные хвосты по p99.
Date.now() тратил CPU на syscall, parseFloat — на парсинг, плохой shape — на cache miss. А потом говорят: "ой да ну какой Node, он же медленный, давайте напишем на Go и пойдем за ванильным лате на растительном"Node быстрый. Просто не мешай ему.
Что еще почитать?
– V8 internals: hidden classes & inline caches — Mathias Bynens, must-read
– Fast properties in V8 — официальный блог V8
– Elements kinds in V8 — про массивы и их shapes
🔥3
Forwarded from PiterJS (Дим)
Node на самом деле быстрый, просто, по возможности, не стоит мешать ему работать.
Почему Delete может снизить перфоманс? Почему порядок полей в объекте не стоит делать разным? И другие вредные советы как сделать жизнь V8 проще при работе с объектами.
Микрооптимизации для работы с объектом, hidden classes, inline cache и почему shape объекта важнее, чем кажется.
Please open Telegram to view this post
VIEW IN TELEGRAM
🔥11❤8
Как чукча решил перед людями выступать
Есть такое развлечение у людей, связанных с написанием кода и долгим созерцанием буков на мониторе: ходить на митапы и пытаться там нетворкаться.
Вот я и был одним из таких людей.
Началось всё давно, когда я ещё даже программистом то не был. Лет 6–7 назад, в один из своих отпусков, я прилетел в солнечный февральский Санкт-Петербург.
До кардинальной смены деятельности оставалось всего полгода. Но мне уже хотелось прикоснуться к прекрасному — к IT-комьюнити.
Мои поиски увенчались успехом, и я, счастливый, что всё так удачно сложилось, посетил PiterJS.
Как сейчас помню: крутейший офис JetBrains рядом с Питерлэндом. Я сидел там, слушал доклад про новомодный тогда Svelte и думал:
«Как круто, наверное, вот так шарить в теме. Быть крутым специалистом. Не просто знать и использовать, но ещё и рассказывать об этом людям. Выступать со сцены перед полным залом, и чтобы эти люди тебя ещё и слушали.
И люди ведь тоже не простые. Им абы что не расскажешь, думал я. Тоже Программисты, Разработчики, Инженеры. И все с большой буквы».
Тогда я получил неимоверный заряд мотивации. Ещё и годовую подписку на WebStorm выиграл.
И, как мне кажется, уже тогда я себе пообещал: я попробую стать таким же крутым, как эти умные люди в очках, чтобы однажды тоже что-то умное втирать со сцены, а меня слушали.
Через полгода я уже учился писать на Node.js за «еду» с утра и до заката. А мне за это ещё и платить начали.
Я всё глубже и глубже погружался в это вот всё. Сначала писал модули, потом строил маленькие системки, затем системы побольше.
Так, год за годом, вместе с выгоранием и хронической усталостью, я копил знания и экспертизу.
А мне всё ещё за это платили.
И вот мне 30. Около 6 лет работы напихали в мою голову такой объём знаний, что им потребовался выход.
Я начал записывать мысли. Сначала просто в заметки, без каких-либо планов. Потом попробовал оформлять эти мысли в статьи и показывать людям.
Так появился канал.
Поначалу он задумывался просто как технический блог про архитектуру и zero deps. Но со временем получилось что-то большее. Личный дневник, как мне кажется.
Что-то я отвлёкся.
Так вот. Мне 30 лет, я пробую вести блог, продолжаю исследовать Node.js и хочу найти новую работу. Ничто не предвещало беды. Но идиллия не может быть вечной.
После очередного митапа, уже на афтапати, мой друг О. говорит:
«Твой последний пост — огонь. Надо с ним выступать. Срочно подавай заявку».
И этим же вечером моя любимая супруга говорит то же самое:
«Я тебе уже несколько лет говорю. Вот и материал у тебя есть, пост огонь, пора».
А я возьми да и вспомни, что когда-то обещал себе стать умным и рассказывать людям со сцены интересное.
Умным я не стал, но пост действительно получился интересный.
Там же, в баре, была подана заявка.
И заявку почему-то приняли. И даже на прогоне сказали, что тема интересная, а доклад хороший.
И вот, спустя каких-то 6–7 лет, я стою на том месте, где выступали умные люди и рассказывали умные вещи. Рассказываю залу что-то умное про Node.js.
И меня в зале даже, кажется, слушают.
Считаю ли я это достижением? Определённо.
Хочу ли я выступать ещё? Однозначно.
Считаю ли я себя «умным человеком в очках»? Пока ещё нет.
Можно ещё многое написать: про страх, про то, как проходило выступление, и какие выводы я сделал. Но оставлю это на потом. Возможно, расскажу в следующих постах.
А пока кушайте кашу, читайте книги и стремитесь стать «умным человеком в очках».
Есть такое развлечение у людей, связанных с написанием кода и долгим созерцанием буков на мониторе: ходить на митапы и пытаться там нетворкаться.
Вот я и был одним из таких людей.
Началось всё давно, когда я ещё даже программистом то не был. Лет 6–7 назад, в один из своих отпусков, я прилетел в солнечный февральский Санкт-Петербург.
До кардинальной смены деятельности оставалось всего полгода. Но мне уже хотелось прикоснуться к прекрасному — к IT-комьюнити.
Мои поиски увенчались успехом, и я, счастливый, что всё так удачно сложилось, посетил PiterJS.
Как сейчас помню: крутейший офис JetBrains рядом с Питерлэндом. Я сидел там, слушал доклад про новомодный тогда Svelte и думал:
«Как круто, наверное, вот так шарить в теме. Быть крутым специалистом. Не просто знать и использовать, но ещё и рассказывать об этом людям. Выступать со сцены перед полным залом, и чтобы эти люди тебя ещё и слушали.
И люди ведь тоже не простые. Им абы что не расскажешь, думал я. Тоже Программисты, Разработчики, Инженеры. И все с большой буквы».
Тогда я получил неимоверный заряд мотивации. Ещё и годовую подписку на WebStorm выиграл.
И, как мне кажется, уже тогда я себе пообещал: я попробую стать таким же крутым, как эти умные люди в очках, чтобы однажды тоже что-то умное втирать со сцены, а меня слушали.
Через полгода я уже учился писать на Node.js за «еду» с утра и до заката. А мне за это ещё и платить начали.
Я всё глубже и глубже погружался в это вот всё. Сначала писал модули, потом строил маленькие системки, затем системы побольше.
Так, год за годом, вместе с выгоранием и хронической усталостью, я копил знания и экспертизу.
А мне всё ещё за это платили.
И вот мне 30. Около 6 лет работы напихали в мою голову такой объём знаний, что им потребовался выход.
Я начал записывать мысли. Сначала просто в заметки, без каких-либо планов. Потом попробовал оформлять эти мысли в статьи и показывать людям.
Так появился канал.
Поначалу он задумывался просто как технический блог про архитектуру и zero deps. Но со временем получилось что-то большее. Личный дневник, как мне кажется.
Что-то я отвлёкся.
Так вот. Мне 30 лет, я пробую вести блог, продолжаю исследовать Node.js и хочу найти новую работу. Ничто не предвещало беды. Но идиллия не может быть вечной.
После очередного митапа, уже на афтапати, мой друг О. говорит:
«Твой последний пост — огонь. Надо с ним выступать. Срочно подавай заявку».
И этим же вечером моя любимая супруга говорит то же самое:
«Я тебе уже несколько лет говорю. Вот и материал у тебя есть, пост огонь, пора».
А я возьми да и вспомни, что когда-то обещал себе стать умным и рассказывать людям со сцены интересное.
Умным я не стал, но пост действительно получился интересный.
Там же, в баре, была подана заявка.
И заявку почему-то приняли. И даже на прогоне сказали, что тема интересная, а доклад хороший.
И вот, спустя каких-то 6–7 лет, я стою на том месте, где выступали умные люди и рассказывали умные вещи. Рассказываю залу что-то умное про Node.js.
И меня в зале даже, кажется, слушают.
Считаю ли я это достижением? Определённо.
Хочу ли я выступать ещё? Однозначно.
Считаю ли я себя «умным человеком в очках»? Пока ещё нет.
Можно ещё многое написать: про страх, про то, как проходило выступление, и какие выводы я сделал. Но оставлю это на потом. Возможно, расскажу в следующих постах.
А пока кушайте кашу, читайте книги и стремитесь стать «умным человеком в очках».
1🔥9❤5❤🔥2
Смена типа тоже не бесплатна
Привет, читатель. Давненько из меня не выходило контента. Пора исправляться. Принёс для тебя дополнение к прошлой статье про объекты.
Я разбирал hidden classes, inline cache и форму объектов. Главный практический совет был простой: если поле опциональное, создай его сразу и положи
Совет рабочий, но неполный. Форма объекта у V8 может остаться прежней, а контракт поля всё равно изменится. И тогда горячая функция тоже поедет на деоптимизацию.
Если через один путь проходят десятки тысяч однотипных объектов, и ты уже полез смотреть за их формой, стоит понимать и вторую половину механики.
Map знает не только форму
У каждого объекта в V8 есть Map, он же hidden class. Map описывает набор полей, их порядок и смещения. Но в дескрипторе поля хранится ещё и его внутренняя representation, то есть способ, которым V8 ожидает хранить значение.
Упрощённо интересующая нас цепочка выглядит так:
Это внутренний контракт хранения. В самом V8 отдельно существует ещё и field type, но для перехода из
Когда V8 много раз видит
Оптимизатор по известному Map читает поле как маленькое целое и строит код под этот контракт.
Потом кто-то делает так:
Строка уже не помещается в
Ключевой момент: это не обязательно создаёт новый Map. Для некоторых расширений V8 обновляет дескриптор на месте, и адрес Map остаётся тем же. Но оптимизированный код зависел не только от адреса Map, а ещё и от representation. Контракт изменился, зависимый код больше нельзя считать безопасным для использования.
Привет, читатель. Давненько из меня не выходило контента. Пора исправляться. Принёс для тебя дополнение к прошлой статье про объекты.
Я разбирал hidden classes, inline cache и форму объектов. Главный практический совет был простой: если поле опциональное, создай его сразу и положи
null, чтобы все объекты сохранили одинаковую форму.Совет рабочий, но неполный. Форма объекта у V8 может остаться прежней, а контракт поля всё равно изменится. И тогда горячая функция тоже поедет на деоптимизацию.
Если через один путь проходят десятки тысяч однотипных объектов, и ты уже полез смотреть за их формой, стоит понимать и вторую половину механики.
Map знает не только форму
У каждого объекта в V8 есть Map, он же hidden class. Map описывает набор полей, их порядок и смещения. Но в дескрипторе поля хранится ещё и его внутренняя representation, то есть способ, которым V8 ожидает хранить значение.
Упрощённо интересующая нас цепочка выглядит так:
Smi маленькое целое, закодированное прямо в tagged-слоте
Double числовое значение с плавающей точкой
HeapObject ссылка на объект в куче: строку, объект, null, undefined и так далее
Tagged широкое представление, которое принимает и Smi, и ссылки
Это внутренний контракт хранения. В самом V8 отдельно существует ещё и field type, но для перехода из
number в string нам достаточно representation.Когда V8 много раз видит
{ x: 42 }, поле x может получить representation Smi.Оптимизатор по известному Map читает поле как маленькое целое и строит код под этот контракт.
Потом кто-то делает так:
obj.x = 'boom'
Строка уже не помещается в
Smi. V8 расширяет representation до Tagged, потому что теперь поле должно принимать и целые числа, и ссылки на объекты в куче.Ключевой момент: это не обязательно создаёт новый Map. Для некоторых расширений V8 обновляет дескриптор на месте, и адрес Map остаётся тем же. Но оптимизированный код зависел не только от адреса Map, а ещё и от representation. Контракт изменился, зависимый код больше нельзя считать безопасным для использования.
🔥2
Вот сам деопт
Минимальный пример на Node 24.17.0 с V8 13.6:
Запускаем:
И получаем:
То есть одна запись строки действительно инвалидировала уже оптимизированную
В этой версии V8
Где здесь подвох с `null`
Вернёмся к совету «создай поле заранее и положи `null`».
Для формы объекта он по-прежнему полезен:
Поле
С числом история другая:
Если код успел оптимизироваться между этими двумя состояниями, расширение поля может инвалидировать зависимую оптимизацию.
Для целочисленного поля стоит сразу дать целочисленное значение:
С
Но не стоит превращать это в очередной карго-культ. Если
А если поле хранит дробные числа, одного
Идеальный вариант для горячей структуры: присвоить реальное значение до того, как код станет горячим.
Расширение происходит не на каждом присваивании
Здесь легко сделать неправильный вывод: будто каждое переключение
Нет. Representation расширяется до
Деопты всё ещё возможны, если горячий код специализировался на фактических значениях. Например, выражение
Это уже другая причина: обратная связь по типам самой операции плюс возможные аллокации строк. Сваливать всё это в одну корзину с field representation удобно только до первого человека, который полезет в
Поэтому я не буду продавать здесь красивое «переключение типов замедляет цикл ровно в два раза». Такой микробенч легко измеряет одновременно чтение поля, смену representation, арифметическую специализацию, конкатенацию и повторную оптимизацию. Цифра получится эффектной, но инженерного смысла в ней будет примерно нисколько.
Защищаемый вывод уже есть в трейсе: первое расширение representation способно инвалидировать весь оптимизированный код, который от неё зависит. Цена конкретного деопта зависит от функции, нагрузки, версии V8 и того, сколько зависимого кода придётся пересобрать.
Минимальный пример на Node 24.17.0 с V8 13.6:
function readX(object) {
return object.x
}
const a = { x: 1 }
const b = { x: 2 }
// Убираем отдельную зависимость от constness поля.
a.x = 3
b.x = 4
for (let i = 0; i < 100_000; i++) {
readX(i & 1 ? a : b)
}
// --allow-natives-syntax
%OptimizeFunctionOnNextCall(readX)
readX(a)
a.x = 'boom'
Запускаем:
node --allow-natives-syntax --trace-deopt demo.js
И получаем:
[marking dependent code ... (readX) for deoptimization,
reason: dependent field representation changed]
То есть одна запись строки действительно инвалидировала уже оптимизированную
readX.В этой версии V8
%HaveSameMap(a, b) остаётся истинным даже после присваивания строки. Форма та же, Map тот же, а деоптимизация всё равно случилась.%OptimizeFunctionOnNextCall и %HaveSameMap являются внутренними средствами диагностики V8. В прод их, разумеется, тащить не стоит.Где здесь подвох с `null`
Вернёмся к совету «создай поле заранее и положи `null`».
Для формы объекта он по-прежнему полезен:
const user = { id, name, role: null }
if (isAdmin) {
user.role = 'admin'
}
Поле
role есть у всех объектов с самого начала. Кроме того, и null, и строка относятся к HeapObject, поэтому именно representation при такой записи расширять не требуется.С числом история другая:
const stats = { score: null } // HeapObject
stats.score = 42 // нужно принять ещё и Smi, получаем Tagged
Если код успел оптимизироваться между этими двумя состояниями, расширение поля может инвалидировать зависимую оптимизацию.
Для целочисленного поля стоит сразу дать целочисленное значение:
const stats = { score: 0 }
stats.score = 42
С
undefined та же проблема, что с null: для V8 это объект в куче, а не числовая заглушка.Но не стоит превращать это в очередной карго-культ. Если
null является честным состоянием бизнес-модели, оставь null. Семантика программы важнее одной потенциальной деоптимизации на прогреве.А если поле хранит дробные числа, одного
0 тоже недостаточно для идеальной стабильности: переход от Smi к Double способен потребовать ещё одно расширение.Идеальный вариант для горячей структуры: присвоить реальное значение до того, как код станет горячим.
Расширение происходит не на каждом присваивании
Здесь легко сделать неправильный вывод: будто каждое переключение
42 → 'boom' → 42 снова деоптимизирует функцию из-за representation.Нет. Representation расширяется до
Tagged один раз и самостоятельно обратно до Smi уже не сужается. После этого и число, и строка помещаются в установленный контракт. Повторной генерализации поля на каждом переключении нет.Деопты всё ещё возможны, если горячий код специализировался на фактических значениях. Например, выражение
object.x + 1 сначала выполняет числовое сложение, а со строкой начинает конкатенацию.Это уже другая причина: обратная связь по типам самой операции плюс возможные аллокации строк. Сваливать всё это в одну корзину с field representation удобно только до первого человека, который полезет в
--trace-deopt.Поэтому я не буду продавать здесь красивое «переключение типов замедляет цикл ровно в два раза». Такой микробенч легко измеряет одновременно чтение поля, смену representation, арифметическую специализацию, конкатенацию и повторную оптимизацию. Цифра получится эффектной, но инженерного смысла в ней будет примерно нисколько.
Защищаемый вывод уже есть в трейсе: первое расширение representation способно инвалидировать весь оптимизированный код, который от неё зависит. Цена конкретного деопта зависит от функции, нагрузки, версии V8 и того, сколько зависимого кода придётся пересобрать.
🔥1
Что делать-то?
Да, в целом ничего :)
Это просто интересные факты про Node.js, так же, как и про Map в прошлой статье.
Но если ты оптимизациофил, то:
- Создавай горячие объекты с полным и стабильным набором полей.
- Для целочисленного поля используй числовое начальное значение, а не
- Присваивай реальное значение до прогрева, особенно если поле может хранить дробные числа.
- Не смешивай число и строку в одном поле без причины.
- Проверяй подозрения через
Что в итоге
Одинаковая форма объекта ещё не гарантирует, что оптимизированный код останется валидным. V8 учитывает representation полей и может встроить это знание в машинный код.
Переход
А
JS разрешает нам менять типы как угодно. V8 тоже не против. Но лучше не менять.
Кушайте кашу, читайте книги и не меняйте типы без необходимости.
Что почитать
• Fast properties in V8, официальный разбор Maps, дескрипторов и быстрых свойств
• Representation в исходниках V8, актуальная внутренняя модель
• MapUpdater в исходниках V8, генерализация полей и обновление зависимого кода
• V8 internals: hidden classes & inline caches, подробный разбор Mathias Bynens
Да, в целом ничего :)
Это просто интересные факты про Node.js, так же, как и про Map в прошлой статье.
Но если ты оптимизациофил, то:
- Создавай горячие объекты с полным и стабильным набором полей.
- Для целочисленного поля используй числовое начальное значение, а не
null или undefined.- Присваивай реальное значение до прогрева, особенно если поле может хранить дробные числа.
- Не смешивай число и строку в одном поле без причины.
- Проверяй подозрения через
--trace-deopt.Что в итоге
Одинаковая форма объекта ещё не гарантирует, что оптимизированный код останется валидным. V8 учитывает representation полей и может встроить это знание в машинный код.
Переход
number → string дорог не потому, что строка сама по себе медленная. Он опасен в момент, когда ломается контракт уже скомпилированной функции. V8 расширяет поле, помечает зависимый код на деоптимизацию и затем работает с новым, более широким представлением.А
null ни хороший, ни плохой. Для ссылочного поля это нормальная заглушка. Для числового поля это уже другой внутренний контракт.JS разрешает нам менять типы как угодно. V8 тоже не против. Но лучше не менять.
Кушайте кашу, читайте книги и не меняйте типы без необходимости.
Что почитать
• Fast properties in V8, официальный разбор Maps, дескрипторов и быстрых свойств
• Representation в исходниках V8, актуальная внутренняя модель
Smi, Double, HeapObject и Tagged• MapUpdater в исходниках V8, генерализация полей и обновление зависимого кода
• V8 internals: hidden classes & inline caches, подробный разбор Mathias Bynens
👍2🔥2