← На главную

noalloc проверяет Go-код на выделения памяти в куче

28.10.2026 18:29 · hackernews

The Consensus Labs выпустила noalloc — экспериментальный набор инструментов и библиотек для Go, который помогает не только убрать выделения памяти в куче, но и не допускать их возвращения при изменении кода. Репозиторий и большая часть документации написаны ИИ под руководством человека. При этом проект уже используется в производственном веб-сервисе и поисковике кода The Consensus. Для установки требуется Go 1.27 или новее.

Функцию проверки обозначают директивой //noalloc:root. CLI просматривает всё достижимое из неё дерево вызовов, указывает строки с аллокациями и показывает цепочки вызовов к ним. Код возврата 1 означает найденные выделения памяти, 2 — невозможность выполнить проверку. Директива //noalloc:exempt позволяет исключить строку и её вызовы с указанием причины, //noalloc:fixed сообщает, что методы типа не увеличивают срезы, а //noalloc:append описывает функции с поведением append. Анализ допускает выделения при ошибке или panic, завершающих корневой вызов, и при однократной инициализации. Для постепенного внедрения предусмотрен baseline, который блокирует новые аллокации.

Пакет bounded содержит Buf, Vec, Slice и Map с ограниченной ёмкостью. Если место заканчивается, запись не выполняется, а контейнер получает признак Full: его можно проверить один раз в конце. Память выделяет разработчик либо контейнеры заимствуют блоки из Pool через Region с заранее заданным бюджетом. Такой подход позволяет ограничить расход памяти на запрос, потоково отправлять ответ через Buf и освобождать все заимствования после обработки. Для исчерпания бюджета нужно заранее выбрать поведение: прервать ответ, отказаться от необязательной оптимизации, отклонить слишком большой ввод или зарезервировать ресурсы на входе.

Генератор jsongen создаёт методы чтения и записи JSON без аллокаций, включая первый вызов. Writer и Reader работают с переданными буферами, а при нехватке ёмкости декодирование завершается ошибкой Full вместо расширения памяти. Генератор отклоняет неподдерживаемые типы, например map и interface. Совместимость со стандартным encoding/json проверяется круговым преобразованием; время после декодирования сохраняет момент, но переводится в UTC. В авторских замерах декодирование ленты из 500 элементов дало ноль аллокаций, хотя другие библиотеки местами работали быстрее.

У инструмента есть существенные ограничения. Он анализирует вывод go build -gcflags=-m и одну конфигурацию сборки, поэтому авторы советуют фиксировать версию toolchain и повторять проверку после обновлений. Неизвестные косвенные вызовы считаются аллоцирующими, а проверяются только пути, достижимые из отмеченных корней. После Region.Release нельзя обращаться к заимствованной памяти; Region нельзя делить между goroutine. Пулы и Map обеспечивают ограниченный расход памяти ценой большей медлительности по сравнению с sync.Pool и стандартной map.

Читать оригинал →