← На главную

Программист собрал git-сервер objgit на Tigris в обход латентности

24.06.2026 16:04 · hackernews

Автор решил проверить, можно ли заставить обычный git-сервер работать на объектном хранилище, а не на локальном диске. Он взял библиотеку billy — прослойку, которая заставляет любой бакет притворяться файловой системой. Изначально billy создавали для go-git (чистая Go-реализация git без привязки к /usr/bin/git). А раз go-git умеет работать через billy, а billy уже умеет говорить с хранилищем Tigris — всё сошлось.

Автор собрал прототип под названием objgit. Одно Go-приложение, никакого локального состояния, даже SSH-ключи лежат в бакете. Удивительно, но оно заработало сразу: push, pull, blame, tag — всё как в обычном git.

Дальше начались проблемы. Git внутри построен на POSIX-идиоме: пишем во временный файл, потом атомарно переименовываем (rename). В S3 такого нет — там был бы копировать+удалить, что ломает семантику. Tigris спасает расширением RenameObject: один запрос, без копирования данных. Ещё одна засада — go-git читает временный pack-файл сразу после создания, а объектное хранилище не позволяет одновременно писать и читать. Выкрутились буферизацией в памяти.

Основное узкое место — тысячи вызовов stat(). Git проверяет существование каждого объекта. На локальном диске это микросекунды, на объектном хранилище — десятки миллисекунд за вызов. При push через SSH или git:// go-git не получал EOF от сокета и вместо пакетной записи pack-файла распаковывал каждый объект по отдельности. Получалось 200 000 запросов на 100 000 объектов — больше получаса ожидания. Решение — научиться определять конец pack-файла по заголовку и чексумме, минуя зависимость от EOF.

При клоне тоже была катастрофа: 8 500 вызовов GetObject на репозиторий размером 200 КБ. Каждый вызов — HTTP-запрос. Исправили дисковым кэшем pack-файлов (они immutable, так что инвалидация не нужна). Ещё одна проблема — лавина ListObjectsV2 при поиске рыхлых объектов (их не было, но git всё равно проверял). Кэш не работал, потому что не учитывал chroot-изоляцию репозиториев. Починили одной строкой кода.

Post-receive hooks реализованы через kefka — sandbox без доступа к файловой системе и сети, только coreutils. При push отправляется код хука из коммита, результат отдаётся как remote:.

Вывод: git оказался идеальным бенчмарком для латентности файловых абстракций. Ничего экзотического — просто каждая невинная операция с диском превращается в сетевой вызов. objgit остаётся экспериментом, автор предупреждает: не пихать туда продакшн-репозитории. Исходники на GitHub.

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