Но почему, почему, почему был светофор зеленый?

Но почему, почему, почему
Был светофор зеленый?
А потому, потому, потому,
Что был он в жизнь влюбленный.

Типизированный язык программирования

Но почему, почему, почему
Был светофор зеленый?
А потому, потому, потому,
Что был он в жизнь влюбленный.

Привет, Хабр!
Недавно, вдохновившись моим опытом, мой товарищ решил приобщиться к моноколёсному комьюнити и купил моноколесо Inmotion V12 Pro. В целом колесо достаточно хорошее, но первая совместная поездка выявила одну проблему, а именно: практически невидимые задние сигналы. Этот недостаток не добавляет безопасности поездкам, поэтому, как всегда, я спешу исправить ситуацию. А что из этого вышло — читайте далее.

Я думал, проект готов к релизу. CI думал иначе — и оказался прав десять раз. История про то, что видно только на чистом раннере.
«Полностью готовый» и локально зелёный проект — а первый же полный прогон CI вскрыл десяток скрытых проблем: версия CMake на Ubuntu 22.04, строгий GCC 11, артефакты с 403 от CDN, ASan под valgrind, недоступный из сети реестр и другие. Показываю каждую проблему с настоящим сообщением об ошибке и решением, а заодно — как поднял свой раннер, выпустил релиз руками без раннеров и ускорил пайплайн с 53 до 15 минут. Мораль: CI ловит ровно то, что невидимо на машине разработчика, — версии инструментов, окружение и сеть.

Демон «ничего не делал» — а одно ядро было загружено на 100%. История про виртуальный COM-порт для Linux/WSL2: PTY, epoll и эмуляция RS485, с кодом и граблями.
Рассказываю, как сделал vseriald — демон, который создаёт виртуальный последовательный порт /dev/ttyV0 в Linux и WSL2 и выводит его в сеть, FIFO или очередь сообщений. Разбираю три неочевидных места: псевдотерминал, после закрытия которого одно ядро уходит в 100%; притормаживание источника в однопоточном epoll-цикле без блокировок; эмуляцию полудуплексного RS485 как конечного автомата с таймингами и коллизиями. Плюс честный ответ на вопрос «зачем это, если есть socat и /dev/pts» — и код из реального проекта.

Всем доброго времени суток. В этой статье разжуем некоторые проблемы OSDev'а в том виде, в котором его хотят видеть люди.
Обсудим «конструкторы ОС» и все его плюсы и недостатки.

Vulkan-рендер для S.T.A.L.K.E.R. OGSR: трава до горизонта, меньше статтеров и новый фундамент Зоны..

Я сделал наручные часы, которые показывают время четырьмя светодиодами в двоичном коде. Захотелось сделать подарок знакомому и заодно пройти весь цикл разработки embedded-устройства: схемотехника, четырёхслойная PCB, прошивка.
В статье расскажу про решения, ошибки (включая ту, из-за которой USB не заработал) и устройство прошивки.
Когда я впервые заинтересовался шифрованием, я знал о шифрах только то, что в них время от времени находят уязвимости. Чтобы хоть как-то разобраться в этой теме без наставника, специальной литературы и (поначалу) без доступа к интернету, я решил проводить опыты над самодельным шифром. Одни идеи сменялись другими, а новые знания из разных источников заставляли многое пересматривать снова и снова. Шифр многократно менялся, пока не приобрёл более-менее стабильные черты. Целью же данной статьи является описание истории создания этого шифра и реализованных в нём принципов, которые позволили обойтись без раундовых ключей, добиться лавинного эффекта за 1-2 раунда и пройти тесты случайности.

Я проверил маленький нейросетевой слой в арифметике GF(137): не через квантизацию готовой float32-модели, а сразу в байтовом конечнополевом представлении. В лучшем замере получилось около 4x по памяти и до 4.86x по времени относительно моей NumPy float32-реализации. Внутри — код нативного ядра, ARM NEON, таблица запусков и честный разбор, где результат не сработал.

Когда моделируешь помехоустойчивые коды, декодер обычно остаётся чёрным ящиком: пишешь ldpcDecode(llr, cfg, 30), comm.TurboDecoder или dvbs2ldpc(1/2) — и получаешь красивый «водопад» BER, не заглядывая внутрь. А самое интересное в современных кодах именно там: не в том, как закодировать, а в том, как декодер из зашумлённого сигнала достаёт правильные биты.
Первая часть заканчивалась предложением: «если интересно разобрать итеративное декодирование LDPC/турбо в деталях или полярные коды с последовательным отменением — пишите в комментариях». Написали — так что эта статья и есть ответ на запрос из комментариев. Читать первую часть необязательно: там мы прошли эволюцию кодов в сотовой связи от GSM до 5G по BER‑кривым в MATLAB, а всё нужное я напомню по ходу. Здесь — вскрываем сами декодеры.
Эта часть открывает ящик. Разберём три декодера, на которых держится всё современное кодирование:
— belief propagation — итеративный обмен сообщениями по графу, ядро LDPC и всего 5G eMBB;
— BCJR + итеративный обмен мнениями — то, что сделало турбо‑коды возможными;
— successive cancellation — последовательное отменение в полярных кодах.
Чтобы видеть каждую строчку, MATLAB‑тулбокс не годится — он прячет алгоритм. Поэтому весь разбор идёт по коду небольшой библиотеки, которую я написал специально для этого — fec‑cpp: header‑only C++17, без единой внешней зависимости, только STL. Её можно прочитать целиком за вечер, и каждый декодер в ней — полсотни строк, которые делают ровно то, что написано в учебнике. Рядом с каждым разбором будет и MATLAB‑эквивалент — чтобы видеть контраст: одна строка тулбокса против явного алгоритма. А в конце — большое сравнение: прогоним обе реализации по одинаковым кодам и наложим их BER‑кривые на одни графики.

Много лет назад моя рутинная работа заключалась в поддержке большой базы кода на C++. Этот проект был настоящим кормильцем всей компании, и в нём предоставлялся публичный HTTP API, через который принимались онлайн-платежи. Речь шла об обработке платежей в размере миллиардов евро ежегодно.
Тогда меня ещё было не назвать опытным C++-разработчиком. Разумеется, я знал о неопределённом поведении, но как о чём-то абстрактном, о беде, которая приключается только с новичками. Как же я был неправ!
В этой статье везде, где написано «структура», я имею в виду «структура или класс».

Всем привет! Я продолжаю развивать свою библиотеку для создания распределённых приложений, которая уже легла в основу новой версии rats-search (распределённого торрент-поисковика) и, судя по всему, UltraVNC (VNC клиент).
Она позволяет развернуть собственную P2P-сеть, связать пользователей между собой и выстроить коммуникацию посредством различных потоков данных (бинарных, строковых и т.п.). Главная особенность — автоматическое обнаружение участников (peer discovery), что крайне актуально в условиях постоянных блокировок и сетевых ограничений.
На данный момент библиотека поддерживает языки C/C++, Android (Java), Python и Node.js (Javascript).
Это очередное обновление и ещё большая стабилизация различных функций. Обо всём подробнее далее.
Последний стабильный релиз на сегодня — 1.0.0. Исходный код и бинарные файлы доступны для скачивания c github.

Если в вашем доме система резервного питания или альтернативной энергии собрана на компонентах Xantrex/Schneider Electric, то эта статья может быть полезна. Собственно, у меня как раз инвертор Xantrex XW 6048, панель управления Conext SCP, солнечный контроллер Conext MPPT 60 150. И всё это связано проприетарной сетью Xanbus. Система работает с 2010 года, солнечный контроллер с 2014г. В 2016г. я начал заниматься умным домом и возникла потребность получения электрических параметров системы для контроля и использования в алгоритмах. Например, для ограничения мощности электрического котла при наличии других потребителей. Часть этих правил описана здесь, но с тех пор их стало больше и они стали сложнее. На сайте производителя к моменту написания этой статьи ссылки на использованный мною Conext ComBox, я найти уже не смог, но изображение этого устройства — на заставке к статье, причем это реальная фотография моей установки.
В 2024г. ComBox перестал работать без объяснения причин. Оживить его известными способами не получилось. Нового такого же на рынке в России ни у кого в наличии по понятным причинам не оказалось, несмотря даже на вывешенные цены. Покупка по параллельному импорту оказалась такой дорогой, что проще отказаться от умного дома :). Однако, без электрических параметров DIY-энтузиасту и любителю умных домов жить совершенно некомфортно.
Пришлось идти по пути сбора электрических параметров с помощью внешних датчиков. Плюс такого решения как минимум в том, что оно переносимо на любое другое оборудование, так как не зависит ни от Xanbus ни от конкретных реализаций Modbus протокола других производителей. И, к тому же, может использоваться для сравнения показаний встроенных датчиков и внешних, если, конечно, к ним будет доступ.

Привет, Хаброжители! Более десяти миллиардов строк кода C++ в настоящее время используется в реальных проектах, и 98 % разработчиков ежедневно находят и исправляют в них ошибки. Даже в критически важных приложениях встречаются баги, проблемы с производительностью и читаемостью. Эта книга поможет выявить их в коде, который вы поддерживаете, и избежать — в коде, который вы пишете.

Если показать любому игровому программисту лекции про пользовательский интерфейс года эдак 2006, а потом показать ему что он наклодовал в современной игре, то он узнает в них почти всё, но с небольшими оговорками. Поменялись названия API и язык кодогенерации, но архитектура и основные идеи остались те же: дерево контролов, свойства с рефлексией, связи между свойствами, шаблоны, абстракция над движком и вечная война за пиксель-в-пиксель.
Пользовательский интерфейс в играх это место, где встречаются все худшие архитектурные требования сразу, на них накладываются требования дизайнера UI, который сидит через стол и просит, чтобы окно появлялось «вот так с анимацией», причем «вот так» зависит выпил ли он чашку кофе или еще нет. Вечером приходит художник, который нарисовал кнопку в фотошопе и хочет, чтобы на экране она выглядела пиксель-в-пиксель, и вы обязаны учесть эти требования, потому что в этой цепочке принятия решений художник стоит ближе к финальной картинке. А еще есть программист игровой логики, который не хочет знать, как называется конкретный лейбл, и не должен этого знать.
Под конец приходит локализатор, который превратил «1 enemy / 2 enemies» в «1 враг / 2 врага / 5 врагов» и зависимость от рода. Иногда заскакивает инженер по портированию, которому надо то же самое окно крутить на PC, консолях или мобилках с разными разрешениями и соотношениями сторон, ну на него пофиг, он сам себе программист и если что, допишет код. И всё эти требования должны как-то жить вместе.
Большая часть студий начинала с написания системы GUI «по месту», т.е. для конкретной игры, под конкретный рендер, с захардкоженной раскладкой, а когда выходила следующая игра, выяснялось, что вытащить старый GUI почти невозможно. Такой UI насквозь срастается с рендером, инпутом, звуком и игровой логикой и каждый следующий проект начинается с фразы «давайте сделаем нормально один раз», и каждая следующая итерация показывала, что «нормально» это не одна задача, а много и одновременно.
Не переключайтесь, будет еще вторая часть про то как этот самый UI мучали от игры к игре...

История о том, как реальная performance-проблема привела к простой exact-оптимизации Hausdorff distance на упорядоченных контурах.

Моделирование спутниковых систем связи в симуляторе компьютерных сетей NS-3 с использованием модуля Satellite.

Расскажу вам одну историю о том, как смог прокачаться в качестве C++-программиста. Мне в этом помогло не чтение стандарта. Я тогда ещё не понимал до конца метапрограммирование с использованием шаблонов (честно говоря, прямо сейчас эту тему изучаю). Нет, просветление наступило, когда я всмотрелся в целую простыню кода на ассемблере x86–64, но не запаниковал, а подумал: “O, нет, нет. ЧТО ТАМ сделал компилятор?”
Читать вывод компилятора — это не какое-то мистическое тёмное искусство, которое практикуют только подстриженные в барбершопах разработчики компиляторов, с закрытыми глазами разбирающиеся в выделении регистров. Это навык. Его можно усвоить, затем в нём напрактиковаться, и результат вас очень удовлетворит. Овладев этим умением, вы больше никогда не будете писать «умные» абстракции как раньше.

Все мы любим envsubst за простоту, но он примитивен. Переходить на Python с Jinja2 ради шаблонизации конфигов в CI/CD — всё равно что стрелять из пушки по воробьям, да и тащить рантайм ради пары переменных не хочется. В мире Go есть неплохие аналоги, но их вес в 100 МБ вгоняет в тоску, когда стремишься к минимализму в Docker-образах.
Теперь всё изменилось так как появился muenvsubst — замена стандартной утилите, написанная на C++17, заточенная под хардкорную шаблонизацию в инфраструктуре. В этой статье я расскажу, как уместить мощь, близкую к Jinja2 (включая циклы, условия, макросы и вызов shell), в статический бинарник весом менее 400 КБ.

В условиях стремительного роста объёмов интернет‑трафика особое значение приобретают высоконагруженные системы. Под этим термином понимают подкласс систем массового обслуживания, предназначенных для обработки большого числа запросов при минимальном времени отклика. Стабильность таких систем определяется их способностью сохранять работоспособность при увеличении нагрузки и обеспечивать предсказуемый рост задержек.
Для достижения требуемого уровня производительности применяется масштабирование. Его принято разделять на два основных подхода: вертикальное масштабирование, при котором увеличиваются вычислительные ресурсы отдельных узлов, и горизонтальное масштабирование, предполагающее добавление в систему дополнительных сервисов, обслуживающих запросы. Однако независимо от выбранного подхода сетевой уровень остаётся критическим фактором, влияющим на производительность. Это связано с тем, что сетевую часть невозможно масштабировать столь же гибко, как остальные компоненты системы.
Так, при вертикальном масштабировании увеличение числа процессоров ускоряет обработку запросов, но количество сетевых интерфейсов остаётся ограниченным: клиенты продолжают взаимодействовать с сетевым адресом, привязанным к конкретной сетевой карте. При горизонтальном масштабировании все запросы проходят через балансировщик нагрузки, который остаётся единственной точкой входа. В результате именно эффективность сетевой обработки может стать узким местом, нивелирующим преимущества масштабирования.
Как следствие, при проектировании высоконагруженных систем необходимо уделять особое внимание организации сетевой обработки. В моей практике эта задача особенно остро проявилась при разработке VPN‑сервиса, который можно рассматривать как типичный пример высоконагруженной системы. В статье будет показано, как применение нестандартных технических решений позволяет существенно повысить скорость сетевой обработки и, как следствие, улучшить общую производительность системы.