Git действительно медленный для 100 000 объектов. Какие-нибудь исправления? - программирование
Подтвердить что ты не робот

Git действительно медленный для 100 000 объектов. Какие-нибудь исправления?

У меня есть "свежий" git -svn repo (11.13 ГБ), который содержит более 100 000 объектов.

Я подготовил

git fsck
git gc

на репо после первоначальной проверки.

Затем я попытался сделать

git status

Время, необходимое для статуса git, находится где угодно: от 2m25.578s и 2m53.901s

Я протестировал статус git, выпустив команду

time git status

5 раз, и все времена пробегали между указанными выше дважды.

Я делаю это на Mac OS X, локально не через виртуальную машину.

Нельзя долго это делать.

Любые идеи? Помощь?

Спасибо.

Edit

У меня есть собеседник, сидящий рядом со мной с сопоставимой коробкой. Меньше оперативной памяти и работает Debian с файловой системой jfs. Его git статус работает в .3 на одном и том же репо (это также git -svn checkout).

Кроме того, я недавно изменил свои права доступа к файлам (до 777) в этой папке, и это значительно сократило время (почему, я понятия не имею). Теперь я могу сделать это где-то между 3 и 6 секундами. Это управляемо, но все же боль.

4b9b3361

Ответ 1

Это сводилось к нескольким пунктам, которые я могу видеть прямо сейчас.

  • git gc --aggressive
  • Открытие прав доступа к файлам 777

Должно быть что-то еще, но это было то, что явно оказало наибольшее влияние.

Ответ 2

git статус должен смотреть каждый файл в репозитории каждый раз. Вы можете сказать, чтобы он не смотрел на деревья, с которыми вы не работаете.

git update-index --assume-unchanged <trees to skip>

источник

Из man-страницы:

Когда эти флаги указаны, имена объектов, записанные для путей не обновляются. Вместо этого эти параметры установлены и отключены без изменений "для путей. бит" принимать без изменений "включен, gitперестает проверять файлы рабочего дерева для возможных изменений, так что вы нужно вручную отключить бит, чтобы сказать git при изменении рабочего дерева файл. Иногда это полезно, когда работа с большим проектом на файловая система с очень медленным lstat (2) системный вызов (например, cifs).

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

Многие операции в git зависят от вашего для эффективной работы файловой системы lstat (2), так что Информация st_mtime для рабочего дерева файлы можно недорого проверить, чтобы узнать, содержимое файла изменилось с версия, записанная в индексе файл. К сожалению, некоторые файловые системы имеют неэффективный lstat (2). Если ваш файловая система - одна из них, вы можете установить" принять неизменный "бит на пути к вам не изменились, чтобы вызвать git не сделайте эту проверку. Обратите внимание, что установка этого параметра бит на пути не означает, что git будет проверьте содержимое файла, чтобы увидеть если он изменился - он делает gitпропустите любую проверку и предположите, что она не изменилось. Когда вы вносите изменения в рабочих файлов дерева, вы должны прямо скажем git об этом отбрасывая бит" предполагать без изменений ", до или после изменения их.

...

Чтобы установить" предполагать неизменным ", бит, используйте параметр -assume-unchanged. к unset, используйте --no-предполагать-без изменений.

Команда смотрит на core.ignorestat переменная конфигурации. Когда это true, пути, обновленные с помощью gitпути обновления-индекса... и обновленные пути с другими командами git, которые обновляют как индексное, так и рабочее дерево (например, gitapply -index, git checkout-index -u, и git read-tree -u) являются автоматически обозначается как" предполагать без изменений ". Обратите внимание, что" предположим неизменный "бит не установлен, если gitupdate-index --refresh находит рабочий файл дерева соответствует индексу (используйте git update-index --really-refresh если вы хотите пометить их как" предположительно без изменений ").


Теперь, очевидно, это решение будет работать только в том случае, если есть части репо, которые вы можете легко игнорировать. Я работаю над проектом подобного размера, и есть определенные деревья, которые мне не нужно проверять на регулярной основе. Семантика git -status делает его вообще проблемой O (n) (n в количестве файлов). Вам нужно оптимизировать для домена, чтобы сделать лучше.

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

Ответ 3

Одним из долгосрочных решений является расширение git для кэширования состояния файловой системы.

Karsten Blees сделал это для msysgit, что резко повышает производительность в Windows. В моих экспериментах его изменение заняло время "git status" с 25 секунд до 1-2 секунд на моей машине Win7, работающей на виртуальной машине.

Карстен меняет: https://github.com/msysgit/git/pull/94

Обсуждение подхода кэширования: https://groups.google.com/forum/#!topic/msysgit/fL_jykUmUNE/discussion

Ответ 4

В общем, мой mac в порядке с git, но если есть много свободных объектов, он становится намного медленнее. Кажется, hfs не очень хорош с большим количеством файлов в одном каталоге.

git repack -ad

Далее

git gc --prune=now

Создает файл с одним пакетом и удаляет оставшиеся оставшиеся объекты. Это может занять некоторое время.

Ответ 5

Вы можете попробовать передать переключатель --aggressive в git gc и посмотреть, помогает ли это:

# this will take a while ...
git gc --aggressive

Кроме того, вы можете использовать git filter-branch для удаления старых коммитов и/или файлов, если у вас есть вещи, которые вам не нужны в вашей истории (например, старые двоичные файлы).

Ответ 6

git status должен быть быстрее в Git 2.13 (Q2 2017), из-за:

В этой последней точке см. совершить a33fc72 (14 апреля 2017 г.) Jeff Hostetler (jeffhostetler).
(слияние Junio ​​C Hamano - gitster - в совершить cdfe138, 24 апреля 2017 года)

read-cache: force_verify_index_checksum

Научите Git пропустить проверку контрольной суммы SHA1-1 в конце индексный файл в verify_hdr(), который вызывается из read_index(), если не установлена ​​глобальная переменная "force_verify_index_checksum".

Учите fsck, чтобы принудительно выполнить эту проверку.

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


Git 2.14 снова улучшает качество работы Git, принимая во внимание " неэкранный кеш", что позволяет Git пропустить считывание неподготовленных каталогов, если их данные stat не изменились, используя поле mtime структуры stat.

Подробнее см. Documentation/technical/index-format.txt.

См. commit edf3b90 (08 мая 2017 г.) Дэвид Тернер (dturner-tw).
(слияние Юнио С Хамано - gitster - в совершить fa0624f, 30 мая 2017 года)

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

Расширение кеширования без следа теперь копируется в этих операциях, что ускорит "git status" (пока кеш недействителен).


В более общем плане, запись в кеш будет также быстрее с Git 2.14.x/2.15

См. commit ce012de, commit b50386c, commit 3921a0b (21 августа 2017 г.) Кевин Уилфорд (``).
(Слияние Юнио С Хамано - gitster - в commit 030faf2, 27 августа 2017 г.

Раньше мы тратили больше, чем необходимо, на выделение и освобождение циклов кусок памяти при записи каждого входа индекса.
Это было оптимизировано.

[That] сэкономит где-то между 3-7%, когда индекс имел более миллиона записей без ухудшения производительности на небольших репозиториях.


Обновление декабрь 2017: Git 2.16 (Q1 2018) предложит дополнительное усовершенствование, на этот раз для git log, так как код для итерации по потерянным объектным файлам только что получил оптимизацию.

См. commit 163ee5e (04 декабря 2017 г.) Деррик Столе (derrickstolee).
(слияние Junio ​​C Hamano - gitster - в commit 97e1f85, 13 декабря 2017 г.

sha1_file: используйте strbuf_add() вместо strbuf_addf()

Замените использование strbuf_addf() на strbuf_add() при перечислении свободные объекты в for_each_file_in_obj_subdir(). Поскольку мы уже проверьте длину и шестнадцатеричные значения строки перед употреблением путь, мы можем предотвратить дополнительные вычисления, уровня.

Один потребитель for_each_file_in_obj_subdir() - это аббревиатура код. OID (идентификаторы объектов) аббревиатуры используют кешированный список свободных объектов (для подкаталога объектов), чтобы быстро выполнять повторные запросы, но есть значительное время загрузки кеша, когда есть много свободных объектов.

Большинство репозиториев не имеют много лишних объектов перед повторной упаковкой, но в случае GVFS (см. "Объявление GVFS (Git Виртуальная файловая система)), репозитории могут расти, чтобы иметь миллионы свободных объектов.
Профилирование 'git log' в Git Для Windows в режиме репо с поддержкой GVFS с ~ 2.5 миллиона потерянных объектов выявлено 12% время CPU было потрачено на strbuf_addf().

Добавьте новый тест производительности на p4211-line-log.sh, что больше чувствительный к загрузке кеша.
Ограничивая 1000 коммитов, мы более точно напоминаем время ожидания пользователя при чтении истории в пейджер.

Для копии репо Linux с двумя пакетами размером ~ 512 МБ и свободными объектами ~ 572K запуск git log -oneline -parents -raw -1000 'имел следующую производительность:

 HEAD~1            HEAD
----------------------------------------
 7.70(7.15+0.54)   7.44(7.09+0.29) -3.4%

Ответ 7

Для чего это стоит, я недавно обнаружил большое несоответствие между командой git status между моими ведущими и dev-ветвями.

Чтобы сократить длинную историю, я отследил проблему до одного файла размером 280 МБ в корневом каталоге проекта. Это была случайная проверка дампа базы данных, поэтому было бы прекрасно удалить его.

Здесь до и после:

⚡ time git status
# On branch master
nothing to commit (working directory clean)
git status  1.35s user 0.25s system 98% cpu 1.615 total

⚡ rm savedev.sql

⚡ time git status
# On branch master
# Changes not staged for commit:
#   (use "git add/rm <file>..." to update what will be committed)
#   (use "git checkout -- <file>..." to discard changes in working directory)
#
#   deleted:    savedev.sql
#
no changes added to commit (use "git add" and/or "git commit -a")
git status  0.07s user 0.08s system 98% cpu 0.157 total

У меня есть 105 000 объектов в магазине, но кажется, что большие файлы являются скорее угрозой, чем многими небольшими файлами.

Ответ 8

Вы также можете попробовать git repack

Ответ 9

Может быть, вы используете антивирус? Я протестировал несколько крупных проектов здесь, в Windows и Linux - это было чертовски быстро!

Я не думаю, что вам нужно сделать git gc в клонированном репо (он должен быть чистым).

Является ли ваш жесткий диск ОК? IOPS и R/W в секунду? Может быть, он поврежден?

Ответ 10

возможно, прожектор пытается индексировать файлы. Возможно, отключите прожектор для вашего кода. Проверьте Activity Monitor и посмотрите, какие процессы запущены.

Ответ 11

Я бы создал раздел, используя другую файловую систему. HFT + всегда был вялым для меня по сравнению с аналогичными операциями в других файловых системах.

Ответ 12

Попробуйте запустить команду Prune, она избавится от лишних объектов

git удаленный исходный черновик