Сохранёнки программиста
6.62K subscribers
1.14K photos
59 videos
10 files
1.75K links
Заметки и ссылки на будущее, чтобы изучить когда будет время.

Разместить рекламу: @tproger_sales_bot

Правила общения: https://tprg.ru/rules

Другие каналы: @tproger_channels

Другие наши проекты: https://tprg.ru/med
Download Telegram
Сколько стоит прочитать одну страницу в 8 КБ из Postgres — трассировка по всем слоям кэшей

Свежий разбор, который хочется выдать каждому, кто проектирует базы «на глазок». Автор словил в продакшене инцидент с IOPS, воспроизвёл ту же патологию на домашнем сервере и померил, во сколько обходится чтение одной и той же страницы на каждом уровне: shared buffers, page cache операционки, локальный NVMe и сетевой диск AWS EBS.

Числа красивые своей наглядностью, каждый слой стоит примерно на порядок дороже предыдущего:

🔘страница в shared buffers — около 1,1 мкс;
🔘в page cache ОС — около 4 мкс;
🔘холодное чтение с локального NVMe — около 78 мкс;
🔘сетевой EBS в продакшене — около 497 мкс, в 124 раза дороже page cache.

Самая поучительная деталь — про порядок чтения. Те же 500 холодных страниц в отсортированном порядке (bitmap heap scan) читаются за 2,8 мс, а в случайном (index scan) — за 39,5 мс. Разница в 14 раз на ровно тех же данных, всю работу делает readahead ядра.

Сохранять бэкендерам и всем, кто хоть раз удивлялся, почему запрос на ноутбуке летает, а в облаке встаёт колом.

Полная статья: https://frn.sh/8kb-read/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
1👍1
Софт рождается между коммитами — Zed представила DeltaDB, контроль версий для эпохи агентов

Команда редактора Zed считает, что Git перестал отражать то, как теперь пишется код: половина работы происходит в диалогах с агентами, а коммит видит только итоговый снимок. DeltaDB записывает каждую операцию между коммитами как отдельную дельту со стабильным идентификатором и сохраняет рядом разговор, который это изменение породил.

Что это даёт:

🔘с любой строки кода можно перейти к диалогу, в котором она появилась, и ко всем последующим обсуждениям;
🔘ссылки на код привязаны к дельтам, а не к номерам строк, поэтому не ломаются, когда код переезжает;
🔘рабочие деревья построены на CRDT: несколько людей и агентов правят одни файлы на разных машинах без конфликтов;
🔘коллега может подключиться к работе, поговорить с агентом и оставить пометки, не дожидаясь commit и push;
🔘агенты получают контекст: могут «спросить» предыдущих агентов, почему код написан именно так.

Git при этом не выбрасывается — остаётся для CI и связи с внешним миром, просто перестаёт быть единственной точкой совместной работы. Бета обещана в ближайшие недели, открыт список ожидания.

Сохранять тем, кто много работает с кодящими агентами и уже ловил себя на том, что контекст решений теряется между сессиями.

Полная статья: https://zed.dev/blog/introducing-deltadb

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Хватит использовать Conventional Commits — провокационное эссе с аргументами, которые сложно отмахнуть

Автор бьёт по стандарту, который многие команды внедрили не задумываясь. Главный тезис: Conventional Commits фокусируют на неважном и обесценивают важное. Тип коммита (fix, feat, chore) стоит на первом месте и обязателен, а scope — область, которую трогает коммит — опционален и прячется в скобках. По мнению автора, всё должно быть наоборот.

Аргументация по пунктам:

🔘всем читателям истории важнее «где», чем «что за тип»: контрибьютор ищет изменения в конкретной подсистеме, дебажащий ищет по компоненту, дежурный при инциденте смотрит на область, где всплеск ошибок;
🔘тип часто избыточен: в fix(compiler): prevent SVG elements from being stripped и без префикса видно, что это багфикс;
🔘обещания стандарта не выполняются: автогенерация changelog ломается на многокоммитных фичах и ревертах, автоопределение semver даёт ложные срабатывания, а триггерить CI по docs: в сообщении опасно — честнее смотреть на изменённые файлы;
🔘ИИ-ассистенты по привычке генерируют Conventional Commits, чем разносят антипаттерн дальше.

Взамен предлагаются scoped commits: префикс с областью и описание. Это даже не новый стандарт — так десятилетиями живут Linux (i2c: virtio: mark device ready...), Git, Go (net/http/cookiejar: add godoc links), FreeBSD, Node.js и nixpkgs.

Текст вышел 5 июня и уже собрал жаркие обсуждения. Сохранять тем, кто пишет гайдлайны для команды: даже если останетесь на Conventional Commits, аргументы стоит знать.

Полная статья: https://sumnerevans.com/posts/software-engineering/stop-using-conventional-commits/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
1
Семь ошибок в архитектурных диаграммах, которые делают почти все

Команда Ilograph собрала второй заход по антипаттернам системных диаграмм (в первой части было ещё семь, итого четырнадцать). Список из тех, где на каждом пункте узнаёшь свои схемы:

🔘подписи типом вместо имени: на диаграмме «Amazon S3» и «AWS Lambda», и непонятно, какой именно бакет и какая функция. Лечится суффиксом типа: Orders Table, Results Bucket;
🔘висящие ресурсы: компонент нарисован, но ни с чем не соединён, и его роль приходится угадывать;
🔘«мастер-диаграмма»: попытка уместить всю систему в одну схему, где смешаны runtime-зависимости, DNS, CDN и деплой. Решение — несколько диаграмм с разных точек зрения;
🔘синдром конвейера: поведение системы рисуют как поток слева направо, хотя реальные взаимодействия ходят туда-обратно. Для этого есть sequence-диаграммы;
🔘бессмысленные анимации: мелькающие стрелки дублируют то, что и так видно, и нужны только для маркетинга;
🔘fan trap: продюсеры и консьюмеры сходятся в одном брокере сообщений, и кто с кем реально общается — не видно. Лечится отрисовкой топиков внутри брокера;
🔘вера, что ИИ построит качественную диаграмму из исходников: на выходе размытые схемы с галлюцинациями и теми же ошибками из пунктов выше, потому что модель не умеет стратегически решать, что включить, а что выкинуть.

Сохранять перед следующим дизайн-ревью: пройтись по списку и проверить свою схему по всем семи пунктам быстрее, чем потом объяснять её голосом.

Полная статья: https://www.ilograph.com/blog/posts/more-common-diagram-mistakes/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
В большинстве компаний 1С и облачная инфраструктура живут в параллельных мирах: DevOps смотрит в Grafana, финдиректор — в 1С, а когда падает оплата, все смотрят друг на друга. На самом деле подружить 1С с современными инструментами мониторинга вполне реально всего за один спринт. В блоге Centicore рассказали, как это сделать.

В статье разбирается, как вытащить метрики из 1С через OData без единой строчки кода, написать Prometheus Exporter на Python и собрать бизнес- и технические метрики на одном дашборде. А заодно — где интеграция обычно ломается и как это пережить.
RCE, которую AMD не хотела чинить: история одного разбора

Автор разозлился на всплывающее консольное окно на игровом ПК, отследил его до AMD AutoUpdate и в наказание декомпилировал программу. Внутри нашлась цепочка на удалённое выполнение кода: список обновлений приходит по HTTPS, но ссылки на сами исполняемые файлы в нём — обычный HTTP, а проверки подписи нет вообще. Атакующий в той же сети подменяет ответ, и апдейтер скачивает и сразу запускает любой бинарник.

Как развивались события:

🔘27 января — уязвимость найдена, 6 февраля — отчёт в AMD;
🔘в тот же день AMD закрывает его со статусом «не будем чинить»: MITM-атаки вне скоупа их баг-баунти;
🔘на следующий день после публикации блог-поста компания передумала и попросила пост убрать;
🔘дальше четыре месяца продлений эмбарго: «затронуты ещё несколько инструментов», «клиенты просят время»;
🔘9 июня, через 124 дня, эмбарго снято и присвоен CVE.

Детали финала достойны отдельного абзаца. Вместо криптографической подписи AMD добавила проверку CRC-32, которая от подмены не защищает. Выплата за находку — ноль долларов: формально вне скоупа. А эксплуатировать дыру всё это время было нельзя по смешной причине: апдейтер падал из-за другого, никем не замеченного бага с редиректом.

Сохранять тем, кто пишет автообновления (HTTPS и подпись бинарников обязательны), и тем, кто хочет понимать, как на самом деле выглядит ответственное разглашение.

Полная статья: https://mrbruh.com/amd2/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2
Почему случайные UUID в роли первичного ключа убивают вставки в SQLite

Разбор с бенчмарками и профилированием о том, как выбор типа первичного ключа меняет скорость записи в разы. Суть проблемы: первичный ключ задаёт физический порядок хранения строк в B-дереве. Случайный UUID4 означает вставки в случайные места дерева, а это бесконечные сплиты страниц и ребалансировки.

Автор вставляет 10 миллионов строк пакетами по миллиону и сравнивает:

🔘обычный INTEGER-ключ: стабильные ~715 мс на миллион, эталон;
🔘UUID4 с WITHOUT ROWID: первый миллион 2649 мс, десятый уже 12586 мс — деградация нелинейная, чем больше таблица, тем хуже, итог до 18 раз медленнее эталона;
🔘UUID7 с WITHOUT ROWID: стабильные ~1250 мс на миллион без всякой деградации.

Весь фокус в том, что UUID7 содержит таймстемп в старших битах, поэтому новые ключи монотонно растут и ложатся в конец дерева, как автоинкремент. UUID4 при этом остаётся медленнее целого числа примерно на 70%: ключ занимает 16 байт против 8, строк на страницу помещается меньше.

Отдельный урок про WITHOUT ROWID: эта опция полезна, когда по первичному ключу часто ищут, но в паре со случайным UUID получается худшее из двух миров — данные лежат и в листьях, и в промежуточных узлах дерева, и ребалансировка дорожает максимально.

Выводы переносятся на любую БД с кластерным индексом, от MySQL InnoDB до SQL Server. Сохранять всем, кто сейчас выбирает схему ключей для нового сервиса.

Полная статья: https://andersmurphy.com/2026/06/05/the-perils-of-uuid-primary-keys-in-sqlite.html

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
CSS: какие части языка неустранимо плохие и как с ними жить

Разбор от Алекса Кладова (matklad, автор rust-analyzer) — взгляд бэкендера, которому пришлось стилизовать свой блог. Он разложил CSS на части, которые работают предсказуемо, и части, которые подведут в самый неожиданный момент, и для каждой плохой нашёл обходной путь.

Главные практические выводы:

🔘первая строка любого CSS-файла — * { box-sizing: border-box; }, иначе padding ломает размеры элементов;
🔘вместо обёрток и div-супа — семантические теги main, article, nav, details: с ними простой classless CSS работает сам;
🔘отступы между детьми удобно задавать через owl-селектор section > *+* { margin-top: 1rem; } — родитель контролирует расстояния, дети ни о чём не знают;
🔘явные media-запросы для простых страниц не нужны: flexbox и max-width на главной колонке дают отзывчивость бесплатно;
🔘браузерные дефолты — ловушка: проблема не в правиле, которое вы написали, а в правиле, на которое вы полагаетесь, не написав его;
🔘font-size задаёт размер виртуальной коробки вокруг глифа, а не сам глиф — выровнять два шрифта помогает font-size-adjust.

Для блога автору хватило примерно 200 строк читаемого CSS без фреймворков.

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

Полная статья: https://matklad.github.io/2026/06/04/css-unavoidable-bad-parts.html

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
Как мы проскочили путь от первого iPhone и сложной разработки под мобильные устройства до эпохи ИИ? Что случилось и к чему это привело — в третьей части цикла об истории российского IT.

Мобильный бум застал индустрию врасплох: было непонятно, как адаптировать сайты под маленькие экраны и что делать со слабой связью. Решением стали нативные приложения — их начали разрабатывать многие компании. Так мы пришли к эпохе супераппов, где собрано всё и сразу.

Приложений, проектов и стартапов становилось больше — начался расцвет российского IT. Но разработчиков не хватало, и на сцену вышли курсы, школы и онлайн-уроки. Желающих войти в профессию оказалось огромное количество, и рынок быстро перегрелся. Теперь новичков заменяет ИИ, а найти работу — задача со звёздочкой. Сегодня гонка за лучшими программистами превратилась в гонку ИИ-инфраструктур.

Так решения порождали новые проблемы, а российская IT-индустрия вышла на новый уровень сложности. Подробнее — в материале на Tproger.
🤗2
Algorithm Visualizer — сайт, где 30+ алгоритмов разобраны пошаговой анимацией

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

Что внутри:

🔘поиск пути и обходы графов: BFS, DFS, Dijkstra, Bellman-Ford;
🔘остовные деревья Краскала и Прима, компоненты связности, потоки в сетях (Edmonds-Karp, Ford-Fulkerson);
🔘сортировки, бинарное дерево поиска, связные списки, дерево рекурсии;
🔘классика собеседований и олимпиад: N-Queens, выпуклая оболочка, машина Тьюринга.

Июньское обновление добавило визуализатор связных списков, рабочее пространство для обходов графа, кратчайшие пути с остовными деревьями и переиспользуемый SVG-компонент дерева с BST.

Работает прямо в браузере, ничего ставить не нужно. Сохранять студентам перед сессией, всем, кто готовится к алгоритмическим секциям собеседований, и менторам — объяснять джуну Дейкстру по анимации сильно проще, чем по псевдокоду.

Полная ссылка: https://tamimehsan.github.io/AlgorithmVisualizer/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
Сжать баг до минимального примера автоматически: про недооценённые test-case reducers

Когда баг воспроизводится на огромном входе — файле, программе, последовательности действий — стандартный совет «сделайте минимальный пример» звучит легко, а руками делается мучительно. Лори Тратт напоминает про инструменты, которые делают это сами: test-case reducers берут падающий вход и ужимают его, часто на 95-99%, до состояния, где удалить уже нечего.

Ключевая идея — reducer ничего не знает про ваш язык и формат. Ему нужен только оракул: функция, которая отвечает «да, этот вход всё ещё интересен», то есть баг по-прежнему воспроизводится. Всё остальное — перебор и выбрасывание кусков.

Что полезно знать:
🔘 reducer языконезависим: тот же инструмент сжимает и C-программу, и JSON, и лог действий, лишь бы был тест на «интересность»;
🔘 написать хороший тест на интересность сложнее, чем кажется: легко получить переусушку, когда вход схлопывается в другой баг, не тот, что вы ловите;
🔘 скорость этого теста решает всё: reducer вызывает его тысячи раз, поэтому его выгодно делать максимально дешёвым;
🔘 сжимать можно не только по длине входа, но и по другим метрикам — длине трейса, числу инструкций, частоте срабатывания ошибки;
🔘 есть приёмы и для недетерминированных багов, которые воспроизводятся через раз.

Сохранять всем, кто хоть раз убил полдня на ручное вырезание строк из репродукции. Навык языконезависимый и не устаревает: дешёвый минимальный пример экономит часы на каждом нетривиальном баге.

Полная статья: https://tratt.net/laurie/blog/2026/test_case_reducers_are_underappreciated_debugging_tools.html

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
Forwarded from Типичный программист
Разработчик заменил 3 ГБ SQLite на десяток мегабайт FST и не потерял в скорости

У финнов есть слово opiskelijassammekin, и если вы не носитель, разобрать его вручную — то ещё удовольствие. Проект Taskusanakirja как раз помогает: вводишь приставку, а словарь ищет финско-английские пары на лету. Раньше под это дело автор держал 3 ГБ SQLite и упирался в размер.

В итоге он перешёл на FST (finite state transducer), статичную структуру данных для префиксного поиска. Бинарник сжался до десятка мегабайт, а отклик остался таким, что глаз не заметит.

Цепляет не столько цифрой, сколько подходом: вместо универсальной базы используется узкая структура, которая делает ровно то, что нужно, и не жрёт лишнего. Хороший напоминание, что иногда оптимизация заключается не в ускорении запросов, а в отказе от лишнего инструмента.
1👍1
p99 0 мс на автодополнение 240 миллионов доменов

Автор поставил себе дерзкую цель: показывать подсказки раньше, чем пользователь успеет отпустить клавишу. Задержку он меряет от момента keyUp до готового результата и закладывает бюджет p99 в 121 мс на два нажатия с паузой между ними. Чтобы в него уложиться, выдача должна быть готова почти мгновенно.

Архитектура делится на две части по распределению запросов:
🔘голова, миллион самых частых доменов из списка Tranco, лежит в памяти как символьный trie с заранее посчитанным топ-8 для каждого префикса;
🔘хвост, все 240 миллионов доменов из CZDS, лежит на SSD как memory-mapped блочный индекс с дельта-сжатием: 27 МБ оглавления в памяти и 2,5 ГБ на диске;
🔘большинство запросов к API отвечают за 2 мс, на нагрузке 1600 запросов в секунду p99 связки nginx и API держится около 15 мс;
🔘оставшаяся задержка упирается в сетевой путь через Cloudflare, поэтому для дальних регионов нужна геобалансировка.

По дороге видно, как требование «мгновенно» раскладывается на конкретные структуры данных и бюджеты по миллисекундам.

Сохранять тем, кто проектирует поиск и автодополнение под нагрузкой и любит, когда задержку считают по слоям.

Полная статья: https://ruurtjan.com/articles/p99-0ms-autocomplete-for-240-million-domain-names

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
2👍1
Сжать GIF без потерь полным перебором: история ZGIF

GIF внутри использует LZW, а не DEFLATE, и это влияет на то, как его сжимать. Существующий flexiGIF уже умеет гибкий разбор с заглядыванием вперёд, но иногда делает хуже: занятый слот в словаре потом аукается. Автор задался вопросом, какой LZW-поток для картинки минимален в принципе, и написал ZGIF, который ищет этот минимум полным перебором. По духу это Zopfli, только для LZW.

Путь к рабочей версии занял несколько подходов, от поиска A* через динамическое программирование к гибриду с отсечением:
🔘первая реализация на Python сжимала картинку 16 на 16 пикселей, всего 256 байт, за 30 минут;
🔘после оптимизаций то же самое стало занимать 4 минуты;
🔘с отсечением и заглядыванием на один шаг скорость упала до 4 секунд;
🔘результат при этом всё равно плотнее, чем у существующих инструментов.

Сохранять тем, кто любит алгоритмы сжатия и истории про то, как наивная идея «давайте переберём всё» доводится до практичной скорости.

Полная статья: https://blog.arusekk.pl/posts/lossless-gif-recompression/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
3❤‍🔥1👍1
Похвала memcached: зачем намеренно держать кеш простым

Автор объясняет, почему в новых проектах снова берёт memcached вместо Redis. Redis он плохим не называет. Просто напоминает, что у простого инструмента есть свои сильные стороны, про которые многие забыли.

Главные мысли разбора:
🔘Redis легко перерастает из кеша в самодельную базу: положить данные через SET проще, чем сделать INSERT, и команда постепенно перестаёт относиться к нему как к временному кешу;
🔘у memcached нет персистентности на диск, и это сделано намеренно: его можно гонять как нагрузку без состояния и не думать о сохранности;
🔘клиентские библиотеки memcached прощают сбои: если сервер упал, get возвращает пустоту, и приложение просто идёт в основной источник данных;
🔘кластеризация живёт на стороне клиента через хеширование ключей по нескольким адресам, упавшая нода выводится из ротации;
🔘автор спокойно поднимает десятки инстансов по 64 МБ почти без накладных расходов.

Сохранять тем, кто выбирает кеш для веба и заодно хочет перечитать аргумент против того, чтобы кеш медленно превращался в критичное хранилище состояния.

Полная статья: https://jchri.st/blog/in-praise-of-memcached/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
MinIO на staging: собственное S3-хранилище вместо облачного счёта

Казалось бы, облачное S3-хранилище на staging — очевидный выбор. Но аватары, документы, отчёты и записи звонков там не удаляют, SLA не нужен, а счёт растёт за хранение и трафик. В гайде разбирают, как поднять MinIO на том же VPS, где крутится staging.

MinIO реализует API Amazon S3 и понимает те же SDK и presigned URL, но стоит ровно столько, сколько диск сервера. Код клиента не меняется: меняются только эндпоинт, регион, ключи и флаг forcePathStyle. Контейнер поднимается за 10–15 минут, HTTPS отдаётся обратному прокси с Let’s Encrypt, а приложение получает отдельного пользователя с политикой только на нужный бакет.

Сохраните, если устали платить за тестовые артефакты или заметили, что staging тестирует не тот путь загрузки, что прод.
Git-сервер без диска: как объектное хранилище научили говорить по git

Git-репозиторий под капотом это объектное хранилище: коммиты, деревья и сами файлы лежат как сжатые объекты с адресацией по содержимому, а ветки и теги это крошечные изменяемые указатели на них. Обычно git-сервер держит всё это на локальной файловой системе одной машины, и она становится единой точкой отказа. Автор решил проверить, что будет, если направить git-сервер прямо в бакет объектного хранилища, без диска, без бинарника git и без базы данных.

Получился objgit, один бинарник, который хранит репозитории в облачном бакете и говорит по трём транспортам: HTTP, классический git:// и SSH. Внутри он опирается на go-git, чистую реализацию протоколов git на Go, и на billy, файловую абстракцию, которую автор натянул на объектное хранилище, чтобы go-git не заметил подмены.

Самое предметное в статье это грабли латентности, разобранные по числу запросов:
🔘push пакета из 100 тысяч объектов разворачивался в 200 тысяч обращений к хранилищу, по одному stat и write на каждый объект, и при задержке около 10 мс это полчаса ожидания;
🔘клон простого репозитория из 318 объектов с пакетом в 200 КиБ до починки кеша делал больше 8500 вызовов GetObject;
🔘поиск объектов по двухсимвольным префиксам каталога давал до 256 вызовов листинга бакета за один клон;
🔘ошибка в кеше приводила к тысячам фоновых листингов каждые 30 секунд в течение 10 минут;
🔘pack-файлы неизменны и адресуются по содержимому, поэтому их можно держать в локальном кеше без инвалидации: первый запрос медленный, дальше скорость файловой системы;
🔘атомарное обновление веток автор делает через расширение RenameObject, переименование объекта за один запрос к хранилищу.

Сохранять тем, кто строит поверх объектных хранилищ или любит истории про то, как привычный инструмент ведёт себя на непривычном бэкенде и во что упирается по числу запросов.

Полная статья: https://www.tigrisdata.com/blog/objgit/

@prog_stuff
Please open Telegram to view this post
VIEW IN TELEGRAM
👍1
VPS vs VDS vs виртуальный хостинг: что выбрать в 2026

Часто сервер выбирают по цене, а потом упираются в нехватку ресурсов, гибкости или поддержки. И почти никто не знает главного: VPS и VDS — это в большинстве случаев одно и то же, разница только в названии. Реально выбор идёт между хостингом (провайдер всё настроил, но конфигурация ограничена) и изолированным сервером с root-доступом.

В подборке 6 провайдеров под разные сценарии: от старта на виртуальном хостинге за ~123 рубля в месяц до VPS с зарубежными локациями. Внутри реальные цены, лимиты, условия по бэкапам, тестовым периодам и подсказки как сделать правильный выбор для своего случая.