Обновить
64K+

Системное программирование *

Обеспечение работы прикладного ПО

90,87
Рейтинг
Сначала показывать
Порог рейтинга
Уровень сложности

Утёкшие горутины теперь ищет сборщик мусора. Проверил, где он молчит

Уровень сложностиСложный
Время на прочтение9 мин
Охват и читатели5.2K

В Go 1.27 профиль goroutineleak вышел из эксперимента: рантайм научился доказывать, что горутину уже некому разбудить. Собрал тулчейн из исходников, прогнал десяток программ и замерил, что детектор находит, где он молчит и во что обходится вызов.

Читать далее

Новости

Как я писал сервер и нечаянно пробил 1М RPS

Уровень сложностиСложный
Время на прочтение4 мин
Охват и читатели4.5K

История об асинхронном серверном EAV‑движке, epoll'е, битовых полях и шардинге, который не смог.

Это должен был быть очередной вялотекущий рутинный проект TCP сервера, listen socket, пул потоков, пул соединений, СУБД и синхронизация всего этого добра. Сказать, что скучно — ничего не сказать.

Но у меня было несколько интересных мыслей и желание реализовать что‑то достойное. Писать чистый и изящный код, чтобы каждая деталь была на своём месте, все структурировано и ничего лишнего. Ресурсы позволяли писать код для удовольствия.

Этот сервер не стоит миллион рублей. Это обычная облачная виртуалка: 4 vCPU, 4.5 ГБ RAM, AlmaLinux 8. И она выдала 1М+ RPS на пакетах по 4 байта. Сервер стоял на 40% CPU.

Я прогнал тесты ещё несколько раз — результат не менялся. Сравнил счетчик сервера со счетчиками эмуляторов. Сервер стабильно держал 1М с копейками. Запросил информацию по производительности NGINX. Да ладно!?

Читать далее

Rust 1.98.0: алгебраические методы для f32,f64, исправление взаимодействия между ManuallyDrop и Box

Время на прочтение3 мин
Охват и читатели4.4K

Команда Rust рада объявить о выходе новой версии Rust — 1.98.0. Rust — это язык программирования, который помогает каждому создавать надёжное и эффективное программное обеспечение.

Если у вас уже установлена предыдущая версия Rust через rustup, вы можете получить 1.98.0 командой:

$ rustup update stable

Если Rust ещё не установлен, вы можете получить rustup на соответствующей странице нашего сайта и ознакомиться с подробными release notes для 1.98.0.

Если вы хотите помочь нам, тестируя будущие релизы, рассмотрите возможность переключиться локально на beta-канал (rustup default beta) или nightly-канал (rustup default nightly). Пожалуйста, сообщайте о любых обнаруженных ошибках!

Читать далее

Написал свой ассемблер, чтобы понять, откуда берётся ff010113. Почти половину моей программы он выдумывает

Уровень сложностиСложный
Время на прочтение13 мин
Охват и читатели15K

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

Что сказала плата?

Компилятор удалил вашу проверку на переполнение. И он прав

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели6.9K

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

Разобраться в UB

Написание ядра ОС с нуля. Часть 3 — Пропуск в высшую лигу

Уровень сложностиСложный
Время на прочтение15 мин
Охват и читатели12K

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

В этой статье мы перейдем в полноценный, современный C++23, и все еще останемся на голом железе. Настроим страницы, GDT и перейдем в 64-битный режим.

Читать далее

Хороший код, минусов нет: встреча «плюсовиков» YADRO и C++ Russia

Уровень сложностиПростой
Время на прочтение2 мин
Охват и читатели9K

У ДДТ был свой ответ на вопрос «что такое осень». И даже не один. У C++-разработчиков — свой: это когда вместо листьев разлетаются корутины, вместо дождя — потоки событий, а select и poll внезапно становятся отличной темой для вечерней встречи. 10 сентября в 18:30 проверим эту версию на мероприятии YADRO и C++ Russia. 

В программе — два технических доклада от разработчиков «Лаборатории Касперского» и YADRO. Перед выступлениями Александр Иргер, эксперт по разработке ПО в области телекоммуникаций, расскажет о планах московского сообщества «плюсовиков» и о том, над какими задачами работают сотни разработчиков на С++ в YADRO. Чтобы присоединиться к встрече в любом формате, пожалуйста, зарегистрируйтесь заранее.

Читать далее

Ветвление оказалось дороже лишней работы: как GitHub разогнал обработку исходного кода до 45 ГиБ/с

Уровень сложностиСложный
Время на прочтение20 мин
Охват и читатели6.7K

GitHub прогоняет регистровую свёртку по каждому байту кода, который попадает в индекс Blackbird, поэтому даже базовая текстовая операция быстро превращается в вопрос производительности. Инженеры обнаружили, что ранний выход из цикла мешает LLVM векторизовать обработку: после удаления break скорость на ASCII выросла до 45+ ГиБ/с на одном ядре. Дальше они пошли ещё глубже и научились сворачивать Unicode прямо в байтовом представлении UTF-8, обходясь без полноценного декодирования символов.

Изучить оптимизацию

Go 1.27: generic-методы, которых не видит reflect

Время на прочтение4 мин
Охват и читатели9.8K

Go 1.27 (на момент написания rc3, финал обещают в августе) приносит generic-методы: метод наконец может объявить собственный тип-параметр. Взял golang:1.27rc3 в Docker и проверил, где у фичи границы. reflect новый метод не видит вообще, хотя go/types на том же типе показывает его в method set — метод доступен компилятору и недоступен через рефлексию, поэтому ни один интерфейс им не удовлетворить, а валидаторы и ORM его не заметят. Померил цену: на 200 инстанцирований с запретом инлайна бинарь с методом больше на 2264 байта, из которых 2000 приходятся на длину имён символов, а не на код; по времени разницы нет — это generic-функция с ресивером и тот же gcshape-стенсилинг. А вот что реально заметит прод на апгрейде: GODEBUG=asynctimerchan=1 теперь роняет процесс до main, encoding/json v1 на движке v2 меняет байты вывода на битом UTF-8, json.RawMessage обзавёлся String() и поменял ваши логи. Плюс замеры нового аллокатора: минус четверть времени на new(16 B) и ноль на 128 байтах.

Читать дальше →

Иммутабельные операционные системы: эволюция, архитектуры и опыт РЕД СОФТ

Время на прочтение7 мин
Охват и читатели5.3K

Привет, Хабр. Меня зовут Кирилл Балашов, я инженер-программист компании РЕД СОФТ. Мы в РЕД СОФТ изучили подходы к иммутабельным, или же неизменяемым операционным системам, сравнили полностью иммутабельную модель и гибридную, и выбрали гибрид для неизменяемого варианта РЕД ОС 8. Сегодня я расскажу, почему такая операционка удобнее для решения определённого круга enterprise-задач и покажу, как она работает.

Читать далее

Написание ядра ОС с нуля. Ч2 — Анатомия памяти

Уровень сложностиСложный
Время на прочтение10 мин
Охват и читатели6.9K

В современных процессорах память — это чудо. Существует уйма технологий, позволяющих пользоваться компьютером так, как мы это делаем каждый день.

В этой статье я постарался рассказать, как же все-таки работает кэш, страничная (виртуальная) память и так далее.

Читать далее

Написание ядра ОС с нуля. Часть 1

Уровень сложностиСложный
Время на прочтение7 мин
Охват и читатели19K

Когда я только знакомился с OSDev, я очень долго искал соответствующие материалы. Находил и на YouTube, и на Habr, и просто какие‑то англоязычные сайты (тогда я не сильно знал английский). Но почти все что я находил было либо незаконченным, либо недостаточно понятным и полным.

В этой статье я постараюсь рассказать все так, как ожидал я это от других.

Читать далее

Как я написал PID 1 для контейнеров на чистом ассемблере: x86-64 и ARM64

Уровень сложностиСредний
Время на прочтение9 мин
Охват и читатели12K

Не потому, что контейнерному миру срочно нужен ещё один init. Есть Tini, есть docker run --init, и для большинства production-сценариев я бы по-прежнему начал именно с них.

Мне скорее хотелось разобрать задачу до самого нижнего уровня: без libc, без runtime, напрямую через Linux syscalls. Заодно проверить, насколько сильно будет отличаться одна и та же реализация на x86-64 и ARM64.

В итоге из небольшого эксперимента получился mini-init-asm: PID 1, который запускает приложение в отдельной process group, передаёт сигналы всей группе, собирает zombie-процессы и умеет корректно завершать контейнер с exit code приложения.

Позже туда добавились subreaper mode и простой restart-on-crash. А сам проект в итоге доехал сначала до Debian unstable, а затем и до testing.

Но началось всё с вопроса: что вообще должен уметь нормальный PID 1 внутри контейнера?

Читать далее

Ближайшие события

Паравиртуализация при отладке графических приложений KasperskyOS в QEMU

Уровень сложностиПростой
Время на прочтение10 мин
Охват и читатели8.2K

Привет! Меня зовут Денис Молодяков, я — тимлид команды графики в KasperskyOS. Мы отвечаем за разработку графического стека полного цикла для микроядерной ОС: от создания низкоуровневых графических драйверов до всего необходимого для фреймворков.

Современная реальность разработки диктует новые правила: удаленка и распределенные команды стали нормой. Моя команда не исключение — ребята базируются в разных регионах. При этом каждому разработчику требуется доступ к аппаратным платформам для сборки, запуска ОС, написания и отладки драйверов. Обеспечение каждого сотрудника полным набором плат сопряжено с серьезными логистическими и финансовыми затратами. В этой статье я хочу рассказать, как мы искали оптимальное решение этой проблемы и почему пришли к использованию методики паравиртуализации.

Читать далее

Чему меня научили десятки AI-агентов: как я в качестве эксперимента написал хранилище Blockstor

Время на прочтение11 мин
Охват и читатели8.3K

Пару месяцев назад я решил провести эксперимент и сделать с нуля clean-room имплементацию LINSTOR, используя его референсы и публичные API-типы. Изначально эта идея зародилась как пятничная шутка: я просто хотел уделить этой задаче минимум времени, запустить ее на фоне и посмотреть, к чему это приведёт. Целью было просто проверить, насколько современные нейросети способны к автономной работе без участия человека. 

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

Читать далее

В заголовке моего ELF есть точка входа. Оказалось, её никто не читает

Уровень сложностиСредний
Время на прочтение10 мин
Охват и читатели8.7K

Три статьи я собирал файл и отдавал его эмулятору, ни разу в него не заглянув. Заглянул. Внутри два разных описания одних и тех же байтов, ответ на вопрос, откуда взялся адрес 0x80000000, и поле, которое я заполнял зря.

Ну, открываем!

64 байта и одна константа: разбор переключения контекста в ядре на Rust

Уровень сложностиСложный
Время на прочтение7 мин
Охват и читатели10K

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

Это неприятная связь. Ассемблеру нужен байтовый доступ к сохранённым регистрам, а раскладку структуры определяет компилятор. Если эти двое разойдутся во мнениях, вы не получите ошибку компиляции. Вы получите ядро, которое пишет регистры мимо и падает где-то далеко от места ошибки.

Читать далее

Родитель засыпал навсегда: чего Rust не делает за вас в ядре ОС

Уровень сложностиСложный
Время на прочтение5 мин
Охват и читатели8.2K

Я пишу ядро операционной системы на Rust. Не потому что собираюсь заменить Linux, а потому что мне интересно, что получится, если закладывать безопасность в архитектуру с нуля, а не встраивать в готовое.

Довольно быстро выяснилась вещь, о которой в разговорах про Rust в системном программировании говорят реже, чем стоило бы. Язык закрывает один класс ошибок и оставляет другой нетронутым. И второй класс ловится куда хуже первого.

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

Читать далее

C++-техрадар: что разработчики действительно готовы брать в работу

Уровень сложностиПростой
Время на прочтение11 мин
Охват и читатели13K

В мае на конференциях C++ Russia и HolyJS мы предложили участникам оценить технологии, инструменты и инженерные практики, с которыми они работают или за которыми следят. Так появились данные для двух технических радаров: по экосистеме C++ и по JavaScript.

Сырые цифры сами по себе рассказывают немного, поэтому мы отдали результаты на разбор эксперту. Виктор Новиков, руководитель группы разработки в «Лаборатории Касперского», посмотрел на распределения голосов и поделился своим мнением, почему CMake уверенно побеждает, а PostgreSQL раскалывает аудиторию пополам. В этой статье — его анализ C++-части исследования. Про техрадар JavaScript мы расскажем в другой статье.

Посмотреть радар и принять участие в голосовании можно на странице проекта.

Читать далее

Тихо неправильные данные хуже упавшего скрипта

Уровень сложностиСредний
Время на прочтение6 мин
Охват и читатели6.5K

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

В работе с FASTA и FASTQ таких мест неприлично много. Почти все они когда‑то были задуманы как удобство.

Вот три, с которыми я сталкивался чаще всего.

Первое. Инструмент пишет FASTQ, а качества у записи нет. Вместо ошибки он подставляет строку из I. Файл получается валидный, парсер доволен, а фильтр по качеству дальше по пайплайну видит идеальные риды и пропускает всё подряд.

Второе. R1 и R2 разъехались: один файл отфильтровали, второй забыли. На выходе абсолютно корректный FASTQ, просто риды спарены не с теми. Формат не нарушен ни в одном байте. Ни один валидатор не возразит.

Третье. Определение Phred‑кодировки по образцу, который одинаково хорошо подходит и под Phred+33, и под Phred+64. Инструмент молча выбирает вариант. Иногда правильный.

Общее у всех трёх одно: вместо ошибки вы получаете правдоподобный результат. И это худший из возможных исходов, потому что ошибку вы бы заметили.

Полгода назад я начал писать fastx, библиотеку и CLI для FASTA/FASTQ на Rust. Основное решение в ней сформулировано так: там, где можно либо угадать, либо признать неоднозначность, признавать неоднозначность.

Как это устроено
1
23 ...