Кратенько о git-lfs
8-ого апреля 2015 года GitHub анонсировал git-lfs.
Суть идеи здравая:
Так как в рабочей копии git всегда хранится вся история изменения файлов и из-за этого работать с большими файлами становится затруднительно. Они предлагают относительно элегантное решение, которое позволяет хранить большие файлы отдельно от git-репозитория.
При этом все взаимодействие с репозиторием и большими файлами (добавление/история/просмотр изменений и т.п.) происходит прозрачно для пользователя.
На момент анонса сам GitHub не предоставлял данный функционал. Мы поигрались с github/git-lfs и github/git-lfs, после чего пришли к выводу, что реализация еще слишком сырая.
Я оставил заявку на бета-тестирование и стал жать…
Бета тестирование
Через некоторое время после получения инвайта я таки взялся за более пристальное изучение git-lfs.
Характеристики репозитория:
- Доступ по SSH;
- Рабочая копия ~3.2Гб;
- Репозиторий до конвертации ~50Гб, после ~22Мб;
- Кол-во LFS-файлов в рабочей копии: 4231.
Замерялось время выкачивания рабочей копии: git clone
После настроки сервера и конвертации существующего репозитория были сделаны следующие выводы:
- Технология все еще сырая;
- В случае использования TortoiseGit на каждый lfs-файл выскакивает черное окошко (исправлено в 0.5.2: #381);
- Работа под Windows происходит чудовищно медленно, при этом под Linux все проседает заметно, но не так фатально (#376).
Производительность
Выяснение причин тормознутости git-lfs привел к следующим результатам: интеграция с git у git-lfs идет при помощи фильтров. При этом каждый файл обрабатывается независимо.
На каждый LFS-файл при этом выполняются следующие действия:
- Команда
git lfs
вызываетgit-lfs
(#377); - Выполняется
git version
для получения версии git-а, которая используется в User-Agent при http-запросах (#382); - Выполняется
git config -l
для загрузки конфигации; - Выполняется
git config -l -f .gitconfig
для загрузки конфигурации из файла .gitconfig, даже если он не существует (#391); - Выполняется через ssh
git-lfs-authenticate
(частично лечится мультиплексированием SSH, для которого нужен #404); - По HTTP выясняется месторасположение файла;
- По HTTP загружается сам файл.
При этом, внезапно:
- Установка SSH соединения занимает ~150 мс - выполняется 1 раз на файл;
- Под Windows создание нового процесса занимает ~150 мс (под Linux ~0 мс) - выполняется 5 раз на файл.
Путем включения мулитиплексирования и убирания лишнего вызова процессов удалось сократить время git clone
на локальной гигабитной сети:
- под Windows с 4970 сек до 3561 сек (в ~1.40 раза).
- под Linux с 1436 сек до 541 сек (в ~2.65 раза).
Что дальше
Исправление ситуации ожидается к версии 1.0.0 за счет перехода на групповое выкачивание файлов (batch API: #414).
До этого надо использовать SSH-мультиплексирование: под Windows так и не удалось заставить работать мультиплексирование с OpenSSH, так что нужно использовать PyTTY (переменная окружения GIT_SSH работает для git-lfs 0.5.3+ #404).
Все исправления для уменьшения вызова новых процессов уже вошли в версию 0.5.2.
При этом надо отметить, что Pull Request-ы рассматриваются очень оперативно. Так что я верю, что GitHub доведет данный функционал до ума.