Способы улучшения производительности git status
У меня есть репо 10 ГБ на машине с Linux, которая находится на NFS. Первый раз git status
занимает 36 минут и последующие git status
занимает 8 минут. Кажется, Git зависит от ОС для кэширования файлов. Только первый git
такие команды, как commit
, status
это включает в себя упаковку / переупаковку всего репо, очень большое время занимает огромное репо. Я не уверен, что вы использовали git status
на таком большом репо, но кто-нибудь сталкивался с этой проблемой?
я пытался git gc
, git clean
, git repack
но время все равно / почти то же самое.
Помогут ли субмодули или какие-либо другие концепции, такие как разбиение репо на более мелкие? Если это так, что лучше для разделения большого репо. Есть ли другой способ улучшить время, затрачиваемое на команды git в большом репо?
15 ответов
Чтобы быть более точным, git зависит от эффективности lstat(2)
системный вызов, так что настройка таймаута кэша атрибутов вашего клиента может помочь.
Руководство по git-update-index
- по сути, ручной режим для git-status
- описывает, что вы можете сделать, чтобы облегчить это, используя --assume-unchanged
флаг, чтобы подавить его нормальное поведение и вручную обновить пути, которые вы изменили. Вы даже можете запрограммировать свой редактор на сброс этого флага каждый раз, когда вы сохраняете файл.
Альтернатива, как вы предлагаете, состоит в том, чтобы уменьшить размер вашей проверки (размер упаковочных файлов здесь не вступает в игру). Возможные варианты: редкая проверка, субмодули или инструмент репо Google.
(Есть ветка списка рассылки об использовании Git с NFS, но она не отвечает на многие вопросы.)
Я также вижу эту проблему в большом проекте, совместно используемом через NFS.
Мне потребовалось некоторое время, чтобы обнаружить флаг -uno, который можно присвоить как git commit, так и git status.
Этот флаг отключает поиск неотслеживаемых файлов. Это значительно уменьшает количество операций NFS. Причина в том, что для того, чтобы git обнаружил неотслеживаемые файлы, он должен искать во всех подкаталогах, поэтому, если у вас много подкаталогов, это повредит вам. Отключая git от поиска неотслеживаемых файлов, вы исключаете все эти операции NFS.
Объедините это с флагом core.preloadindex, и вы сможете получить разумную производительность даже на NFS.
Попробуй git gc. Также может помочь git clean.
ОБНОВЛЕНИЕ - Не уверен, откуда пришло отрицательное голосование, но руководство git определенно заявляет:
Запускает ряд служебных задач в текущем репозитории, таких как сжатие версий файлов (для уменьшения места на диске и увеличения производительности) и удаление недоступных объектов, которые могли быть созданы из предыдущих вызовов git add.
Пользователям рекомендуется запускать эту задачу на регулярной основе в каждом хранилище, чтобы поддерживать хорошее использование дискового пространства и хорошую производительность.
Я всегда замечаю разницу после запуска git gc, когда состояние git медленное!
ОБНОВЛЕНИЕ II - Не уверен, как я пропустил это, но OP уже попробовал git gc и git clean. Клянусь, этого изначально не было, но я не вижу никаких изменений в правках. Простите за это!
Если в вашем git repo интенсивно используются подмодули, вы можете значительно повысить производительность git status, отредактировав файл конфигурации в каталоге.git и установив ignore = dirty
на любых особенно больших / тяжелых подмодулях. Например:
[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty
Вы потеряете удобство напоминания о том, что в любом из подмодулей есть незакрепленные изменения, о которых вы, возможно, забыли, но вы все равно сохраните основное удобство - знать, когда подмодули не синхронизированы с основным репо. Кроме того, вы все равно можете изменить свой рабочий каталог на сам подмодуль и использовать в нем статус git, как обычно, чтобы увидеть больше информации. Смотрите этот вопрос для более подробной информации о том, что означает "грязный".
Производительность статуса git должна улучшиться с Git 2.13 (2 квартал 2017 года).
Смотрите коммит 950a234 (14 апреля 2017 г.) Джеффа Хостетлера ( jeffhostetler
)
(Объединено Юнио С Хамано - gitster
- в коммите 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
)
(Объединено Юнио С Хамано - 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
с:
коммит f39a757, коммит 3ca1897, коммит fd9b544, коммит d7d1b49 (09 января 2018) Джеффом Хостетлером (
jeffhostetler
)
(Объединено Юнио С Хамано -gitster
- в комитете 4094е47, 08 марта 2018 года)
"git status
"может потратить много циклов для вычисления отношения между текущей веткой и ее восходящим потоком, которую теперь можно отключить с помощью"--no-ahead-behind
вариант.совершить ebbed3b (25 февраля 2018 г.) Дерриком Столи (
derrickstolee
)
revision.c
: уменьшить количество запросов к объектной базе данныхВ
mark_parents_uninteresting()
мы проверяем наличие объектного файла, чтобы увидеть, следует ли нам рассматривать коммит как проанализированный. В результате устанавливается бит "parsed" в коммите.Изменить условие только для проверки
has_object_file()
если результат изменит разобранный бит.Когда локальная ветвь отличается от своей вышестоящей ссылки, "
git status
"будет вычислять счет вперед / назад.
Это используетpaint_down_to_common()
и хитыmark_parents_uninteresting()
,На копии репозитория Linux с локальным экземпляром "master" за удаленной веткой "
origin/master
"~60000 коммитов, мы находим производительность"git status
"с 1,42 секунды до 1,32 секунды, при относительной разнице -7,0%.
git config --global core.preloadIndex true
Сделал работу за меня. Проверьте официальную документацию здесь.
В нашей кодовой базе, где мы имеем где-то в диапазоне 20 - 30 подмодулей,git status --ignore-submodules
ускорил дело ради меня. Обратите внимание, что это не будет сообщать о статусе субмодулей.
Что-то, что еще не было упомянуто, - это активировать кэш файловой системы на компьютерах с Windows (файловые системы linux совершенно разные, и git был оптимизирован для них, поэтому, вероятно, это помогает только для Windows).
git config core.fscache true
В крайнем случае, если git все еще работает медленно, можно отключить проверку времени модификации, так что git должен выяснить, какие файлы изменились.
git config core.ignoreStat true
НО: измененные файлы должны быть добавлены самим разработчиком git add
, Git не находит изменений сам.
В Git 2.40 (1 квартал 2023 г.) сообщение с советом, данное "
Он лучше иллюстрирует все параметры конфигурации, которые вы можете применить, чтобы получить более быстрый/быстрый .
См. status
(30 ноября 2022 г.) rudyrigot
).
(Объединено gitster
-- в
: модернизируйте совет git-status "медленные неотслеживаемые файлы" Подписал: Руди Риго
( ) может быть медленным при наличии большого количества неотслеживаемых файлов и каталогов, поскольку Git должен выполнять поиск по всему рабочему дереву, чтобы перечислить их.
Когда он слишком медленный, Git печатает совет с истекшим временем поиска и предложением отключить поиск с помощью параметра.
Это предложение также содержит предупреждение, которое может отпугнуть некоторых пользователей.Однако в эти дни,
-uno
не единственный вариант.
Git может сократить время, затрачиваемое на перечисление неотслеживаемых файлов, кэшируя результаты предыдущих вызовов, когдаcore.untrackedCache
иcore.fsmonitor
функции включены.Обновите справочную страницу, чтобы объяснить эти параметры конфигурации, и обновите рекомендации, чтобы предоставить более подробную информацию о текущей конфигурации и обратиться к обновленной документации.
теперь включает в свою
НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ И ПРОИЗВОДИТЕЛЬНОСТЬ
может быть очень медленным в больших рабочих деревьях, если/когда ему нужно искать неотслеживаемые файлы и каталоги.
Существует множество параметров конфигурации, позволяющих ускорить это, либо избегая работы, либо используя кешированные результаты предыдущих команд Git.
Не существует единого оптимального набора настроек, подходящего для всех.Мы перечислим сводку соответствующих параметров, чтобы помочь вам, но прежде чем перейти к списку, вы можете запустить снова, потому что ваша конфигурация может уже кэшировать результаты, поэтому последующие запуски могут быть быстрее.
The
--untracked-files=no
флаг илиstatus.showUntrackedfiles=false
config (оба варианта см. выше): укажите, что не следует сообщать о неотслеживаемых файлах. Это самый быстрый вариант. не будет перечислять неотслеживаемые файлы, поэтому вам нужно помнить, создаете ли вы какие-либо новые файлы и вручнуюgit add
их.
advice.statusUoption=false
(видетьgit config
): установка этой переменной вfalse
отключает предупреждающее сообщение, когда перечисление неотслеживаемых файлов занимает более 2 секунд. В большом проекте это может занять больше времени, и пользователь может уже принять компромисс (например, использование «-uno» может быть неприемлемым вариантом для пользователя), и в этом случае нет смысла выдавать предупреждающее сообщение, и в таком случае лучше отключить предупреждение.(видеть
): включить функцию неотслеживаемого кеша и искать только те каталоги, которые были изменены с момента предыдущей команды.
Git запоминает набор неотслеживаемых файлов в каждом каталоге и предполагает, что если каталог не был изменен, то и набор неотслеживаемых файлов внутри не изменился.Это намного быстрее, чем перечисление содержимого каждого каталога, но все же не без затрат, потому что Git все еще должен искать набор измененных каталогов. Неотслеживаемый кеш хранится в
.git/index
файл. Сокращение затрат на поиск неотслеживаемых файлов немного компенсируется увеличением размера индекса и стоимостью его обновления. Это сокращение времени поиска обычно стоит дополнительного размера.
core.untrackedCache=true
иcore.fsmonitor=true
илиcore.fsmonitor=<hook_command_pathname>
(видетьgit update-index
): включить функции неотслеживаемого кеша и FSMonitor и выполнять поиск только в тех каталогах, которые были изменены с момента выполнения предыдущей команды.Это быстрее, чем использовать только неотслеживаемый кеш, потому что Git также может избежать поиска измененных каталогов.
Git должен только перечислить точный набор каталогов, которые недавно изменились. Хотя функцию FSMonitor можно включить без неотслеживаемого кеша, в этом случае преимущества значительно уменьшаются.Обратите внимание, что после включения функций неотслеживаемого кеша и/или FSMonitor может пройти некоторое время.
git status
команды для разогрева различных кешей, прежде чем вы увидите улучшенное время команд.
Это нормально.
Хорошо, в это довольно трудно поверить, если бы я не видел своими глазами ... У меня была очень ПЛОХАЯ производительность на моем новом рабочем ноутбуке,
git status
занимает от 5 до 10 секунд даже для самого глупого репозитория. Я попробовал все советы в этой теме, потом заметил, что
git log
был медленным, поэтому я расширил свой поиск общей медлительности новой установки git и нашел это https://github.com/gitextensions/gitextensions/issues/5314#issuecomment-416081823
в отчаянии я попытался обновить графический драйвер своего ноутбука и ...
Святой Санта-Клаус дерьмо ... это сделало свое дело!
...для меня тоже!
Таким образом, очевидно, что драйвер видеокарты здесь имеет какое-то отношение ... трудно понять, почему, но теперь производительность "такая, как ожидалось"!
Остатки index.lock
файлы
git status
может быть патологически медленным, когда у вас есть остатки index.lock
файлы.
Особенно это случается, когда у вас git submodules
, потому что тогда вы часто не замечаете такие оставшиеся файлы.
Резюме: Бегиfind .git/ -name index.lock
, и удалите оставшиеся файлы, убедившись, что они действительно не используются какой-либо запущенной программой.
Детали
Я обнаружил, что мой статус оболочки git был очень медленным в моем репо, с git 2.19 на Ubuntu 16.04.
Закопался и обнаружил, что /usr/bin/time git status
в моем assets
Подмодуль git занял 1,7 секунды.
Найдено с strace
этот мерзавец читает все мои большие файлы с помощью mmap
. Обычно этого не происходит, обычноstat
достаточно.
Я погуглил проблему и обнаружил проблему с использованием индекса и Racy Git.
Пытался git update-index somefile
(в моем случае gitignore
в проверке подмодуля) показано здесь,
но это не удалось с
fatal: Unable to create '/home/niklas/src/myproject/.git/modules/assets/index.lock': File exists.
Another git process seems to be running in this repository, e.g.
an editor opened by 'git commit'. Please make sure all processes
are terminated then try again. If it still fails, a git process
may have crashed in this repository earlier:
remove the file manually to continue.
Это классическая ошибка. Обычно вы замечаете это при любой операции git, но для подмодулей, которые вы нечасто используете, вы можете не замечать этого месяцами, потому что он появляется только при добавлении чего-либо в индекс; предупреждение не появляется только для чтенияgit status
.
Удаление index.lock
файл, git status
сразу стало быстро, mmaps
исчез, и теперь он более чем в 1000 раз быстрее.
Итак, если ваш статус git неестественно медленный, проверьте find .git/ -name index.lock
и удалите остатки.
Частой причиной медлительности больших репозиториев являетсяstatus
проверка актуальности команды с удаленной веткой — установите эту конфигурацию уровня репо, чтобы отключить ее:
git config status.aheadBehind false
Я не знаю, какой в этом смысл, но для меня статус занимал 30 минут, я перепробовал все, что мог найти в Интернете, наконец, я сделал git reset
У меня были сотни изменений, которые я применил из stash, где stash был создан из другой ветви, но применен к этой ветви, все они были подготовлены, но не зафиксированы (просто объясняя, что я сделал по-другому, прежде чем столкнуться с этой проблемой), git reset
заняло 15 минут, но после этого все стало работать быстро, менее чем за секунду для статуса. Я не эксперт по git, просто рассказываю, что решило мою проблему, надеюсь, это поможет другим, кто попадет на эту страницу.
В качестве теста попробуйте временно отключить защиту в реальном времени для антивирусного программного обеспечения. Если это проблема, поменяйте антивирус.
Показательный пример: у меня был запущен Webroot , и на выполнение каких-либо действий с Git уходило от 30 до 60 секунд. Приостановил защиту в реальном времени, и внезапно моя первоначальная производительность вернулась с обновлениями за доли секунды и быстрой, быстрой системой.
Я выбрал Webroot, так как он славится минимальным влиянием на производительность системы, но в данном случае он метафорически заливал мой процессор патокой.
Это довольно старый вопрос. Хотя я удивлен, что никто не прокомментировал двоичный файл, учитывая размер репозитория.
Вы упомянули, что ваш репозиторий git составляет ~10 ГБ. Похоже, что помимо проблемы с NFS и других проблем с git (решаемыхgit gc
и изменение конфигурации git, как указано в других ответах), команды git (git status, git diff, git add) могут быть медленными из-за большого количества двоичных файлов в репозитории. git плохо справляется с обработкой двоичного файла. Вы можете удалить ненужный двоичный файл, используя следующую команду (пример приведен для файла NetCDF; предварительно сделайте резервную копию репозитория git):
git filter-branch --force --index-filter \
'git rm --cached --ignore-unmatch *.nc' \
--prune-empty --tag-name-filter cat -- --all
Не забудьте поместить '*.nc' в файл gitignore, чтобы git не повторно принял файл.