Производительность git-lfs

Кратенько о 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 доведет данный функционал до ума.

comments powered by Disqus