it-swarm-ru.tech

Способы улучшения производительности git status

У меня есть репо 10 ГБ на машине с Linux, которая находится на NFS. Первый раз git status занимает 36 минут, а последующий git status занимает 8 минут. Кажется, Git зависит от ОС для кэширования файлов. Только первые команды git, такие как commit, status, которые включают в себя упаковку/переупаковку всего репо, требуют очень много времени для огромного репо. Я не уверен, что вы использовали git status в таком большом репо, но кто-нибудь сталкивался с этой проблемой?

Я пробовал git gc, git clean, git repack, но затраченное время остается/почти таким же.

Поможут ли субмодули или какие-либо другие концепции, такие как разбиение репо на более мелкие Если это так, что лучше для разделения большого репо. Есть ли другой способ улучшить время, затрачиваемое на команды git в большом репо?

65
Senthil A Kumar

Чтобы быть более точным, git зависит от эффективности системного вызова lstat(2), поэтому настройка вашего клиента "таймаут кэширования атрибута" может помочь.

Руководство для git-update-index - по сути, ручной режим для git-status - описывает, что вы можете сделать, чтобы облегчить это, путем используя флаг --assume-unchanged , чтобы подавить его нормальное поведение и вручную обновить пути, которые вы изменили. Вы даже можете запрограммировать свой редактор на сброс этого флага каждый раз, когда вы сохраняете файл.

Альтернатива, как вы предлагаете, состоит в том, чтобы уменьшить размер вашей проверки (размер файлов пакета здесь не учитывается). Возможные варианты: редкая проверка, субмодули или инструмент Google repo .

(Существует список рассылки тема об использовании Git с NFS , но он не отвечает на многие вопросы.)

40
Josh Lee

Я также вижу эту проблему в большом проекте, совместно используемом через NFS.

Мне потребовалось некоторое время, чтобы обнаружить флаг - uno, который может быть присвоен как git commit, так и git status.

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

Объедините это с флагом core.preloadindex, и вы сможете получить разумную производительность даже на NFS.

32
user1077329

Попробуйте git gc . Кроме того, git clean может помочь.

UPDATE - Не уверен, откуда пришло отрицательное голосование, но в руководстве по git конкретно сказано:

Выполняет ряд служебных задач в текущем репозитории, таких как сжатие файловых ревизий (для уменьшения места на диске и для повышения производительности ) и удаление недоступных объектов, которые могли быть созданы из предыдущих вызовов git add.

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

Я всегда замечаю разницу после запуска git gc, когда состояние git медленное!

ОБНОВЛЕНИЕ II - Не уверен, как я это пропустил, но ОП уже попробовал git gc и git clean. Клянусь, этого изначально не было, но я не вижу никаких изменений в правках. Простите за это!

25
Jabari

Если в вашем git-репо интенсивно используются подмодули, вы можете значительно повысить производительность состояния git, отредактировав файл конфигурации в каталоге .git и установив ignore = dirty для любых особенно больших/тяжелых подмодулей. Например:

[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty

Вы потеряете удобство напоминания о том, что в любом из подмодулей есть неустановленные изменения, о которых вы, возможно, забыли, но вы все равно сохраните основное удобство - знать, когда подмодули не синхронизированы с основным репо. Кроме того, вы все равно можете изменить свой рабочий каталог на сам подмодуль и использовать в нем статус git, как обычно, чтобы увидеть больше информации. Смотрите этот вопрос для более подробной информации о том, что означает "грязный".

15
beno

Производительность статуса git должна улучшиться с Git 2.13 (2 квартал 2017 года).

Смотрите commit 950a234 (14 апреля 2017 г.) по Джефф Хостетлер (jeffhostetler) .
(Объединено с Junio ​​C Hamano - gitster - in commit 8b6bba6 , 24 апреля 2017 г.)

> string-list: использовать макрос ALLOC_GROW при восстановлении string_list

Используйте макрос ALLOC_GROW() при восстановлении массива string_list, а не просто увеличив его на 32.
Это оптимизация производительности.

Во время состояния очень большого репо и множества изменений значительный процент от общего времени выполнения тратится на пересечение массива wt_status.changes .

Это изменение уменьшает время в wt_status_collect_changes_worktree() со 125 до 45 секунд в моем очень большом хранилище.


Кроме того, Git 2.17 (Q2 2018) представит новую трассировку для измерения времени, потраченного на операции с индексами.

Смотрите коммит ca54d9b (27 января 2018 г.) по Нгуен Тай Нгок Дуй (pclouds) .
(Объединено с Junio ​​C Hamano - gitster - в коммит 090dbea , 15 февраля 2018 г.)

trace: мера времени, потраченного на операции с индексами

Все известные блоки тяжелого кода измеряются (кроме доступа к объектной базе данных). Это должно помочь определить, эффективна ли оптимизация или нет.
Неоптимизированный git-статус выглядел бы примерно так:

0.001791141 s: read cache ...
0.004011363 s: preload index
0.000516161 s: refresh index
0.003139257 s: git command: ... 'status' '--porcelain=2'
0.006788129 s: diff-files
0.002090267 s: diff-index
0.001885735 s: initialize name hash
0.032013138 s: read directory
0.051781209 s: git command: './git' 'status'

Тот же Git 2.17 (Q2 2018) улучшает git status:

revision.c: уменьшить количество запросов к базе данных объектов

В mark_parents_uninteresting() мы проверяем наличие объектного файла, чтобы увидеть, следует ли нам рассматривать коммит как проанализированный. В результате устанавливается бит "parsed" в коммите.

Измените условие, чтобы проверить только has_object_file(), если результат изменит анализируемый бит.

Когда локальная ветвь отличается от своей вышестоящей ссылки, "git status" будет вычислять счет вперед/назад.
Это использует Paint_down_to_common() и нажимает mark_parents_uninteresting().

На копии репозитория Linux с локальным экземпляром "master" за удаленной веткой "Origin/master" с ~ 60 000 коммитов мы обнаружили, что производительность "git status" снизилась с 1,42 секунды до 1,32 секунды при относительной разнице -7,0 %.

7
VonC

В нашей кодовой базе, где мы имеем где-то в диапазоне 20-30 подмодулей,
git status --ignore-submodules
резко ускорили для меня ситуацию. Обратите внимание, что это не будет сообщать о состоянии подмодулей.

1
citysurrounded

git config --global core.preloadIndex true

Сделал работу за меня. Проверьте официальную документацию здесь .

1
klimat

Я не знаю, какой в ​​этом смысл, но для меня статус занимал 30 минут, я перепробовал все, что смог найти в Интернете, наконец, я сделал git reset У меня было 100 изменений, которые я применил из stash, где был создан stash из другая ветвь, но примененная к этой ветке, все они были подготовлены, но не зафиксированы (просто объясняя, что я сделал по-другому, прежде чем столкнуться с этой проблемой), git reset занял 15 минут, но после этого все начало работать быстро, менее чем за секунду для статуса. Я не эксперт по git, просто рассказываю, что решило мою проблему, надеюсь, это поможет другим, кто попадет на эту страницу.

0
Vivek