Есть ли способ ограничить объем памяти, который использует git gc?

Я размещаю репозиторий git на общем хосте. В моем репозитории обязательно есть пара очень больших файлов, и каждый раз, когда я сейчас пытаюсь запустить «git gc» в репозитории, мой процесс уничтожается поставщиком общего хостинга за использование слишком большого объема памяти. Есть ли способ ограничить объем памяти, который может потреблять git gc? Я надеюсь, что он сможет обменять использование памяти на скорость и просто займет немного больше времени, чтобы выполнить свою работу.


person sam2themax    schedule 22.06.2010    source источник
comment
связанный с постимумом: stackoverflow.com/a/10293304/274502   -  person cregox    schedule 30.08.2012
comment
Да, у Dreamhost была похожая проблема (которой помечен этот вопрос). Не так много случаев, когда git убивали, но darcs (другая система контроля версий) всегда убивалась, поэтому ее невозможно использовать на Dreamhost.com   -  person imz -- Ivan Zakharyaschev    schedule 25.02.2015


Ответы (5)


Да, взгляните на страницу справки для git config и посмотрите на параметры pack.*, в частности, pack.depth, pack.window, pack.windowMemory и pack.deltaCacheSize.

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

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

person CB Bailey    schedule 22.06.2010

Я использовал инструкции по этой ссылке< /а>. Та же идея, что предложил Charles Baileys.

Копия команд здесь:

git config --global pack.windowMemory "100m"
git config --global pack.packSizeLimit "100m"
git config --global pack.threads "1"

Это сработало для меня на hostgator с учетной записью общего хостинга.

person hopeithelps    schedule 06.01.2012
comment
Спасибо! Это работает для меня, но я думаю, что во второй строке опечатка - нет параметра SizeLimit; он должен читать: git config --global pack.packSizeLimit 100m - person Max; 01.02.2012
comment
Это сработало отлично. Если сначала это не сработает, попробуйте установить нижний предел для windowMemory и packSizeLimit. В моем случае 25 м были золотым пятном. - person jsapara; 09.08.2012
comment
Я изменил название опции. Исходная ссылка битая, не знаю, куда ее указать. - person phunehehe; 23.09.2013
comment
Я обновил неработающую ссылку на сохранение с Wayback Machine. - person Alex Peters; 22.10.2019
comment
Кажется, у меня работает, чтобы избежать фатальных сбоев, но теперь я получил предупреждение: неоптимальный пакет - нехватка памяти (но git все равно завершается). Вероятно, я должен попытаться установить размеры более 100 МБ и посмотреть, завершится ли он. В конце концов, изначально он пытался сделать это с 24 потоками, поэтому ограничение до 1 уже должно сильно помочь... - person Nobody; 11.11.2019

Использование памяти Git repack: (pack.deltaCacheSize + pack.windowMemory) × pack.threads. Соответствующие значения по умолчанию: 256 МБ, неограниченно, nproc.

Дельта-кэш бесполезен: большая часть времени тратится на вычисление дельт в скользящем окне, большая часть которых отбрасывается; кэширование оставшихся в живых, чтобы их можно было повторно использовать один раз (при написании), не улучшит время выполнения. Этот кеш также не распределяется между потоками.

По умолчанию память окна ограничена через pack.window (gc.aggressiveWindow). Ограничение упаковки таким образом — плохая идея, потому что размер рабочего набора и эффективность будут сильно различаться. Лучше всего поднять оба значения до гораздо более высоких значений и полагаться на pack.windowMemory, чтобы ограничить размер окна.

Наконец, у многопоточности есть недостаток разделения рабочего набора. Уменьшение pack.threads и увеличение pack.windowMemory так, чтобы общая сумма оставалась неизменной, должно улучшить время выполнения.

В repack есть и другие полезные настройки (pack.depth, pack.compression, параметры растрового изображения), но они не влияют на использование памяти.

person Tobu    schedule 08.01.2015
comment
Не кажется полной правдой? У вас есть идея: stackoverflow.com/questions/42175296/ - person Alex; 11.02.2017

Вы можете отключить дельта-атрибут, чтобы отключить дельта-сжатие только для больших двоичных объектов с этими путями:

В foo/.git/info/attributes (или foo.git/info/attributes, если это голый репозиторий) (см. дельта-запись в gitattributes и см. gitignore для синтаксиса шаблона):

/large_file_dir/* -delta
*.psd -delta
/data/*.iso -delta
/some/big/file -delta
another/file/that/is/large -delta

Это не повлияет на клоны репозитория. Чтобы повлиять на другие репозитории (т. е. клоны), поместите атрибуты в файл .gitattributes вместо файла info/attributes (или в дополнение к нему).

person Chris Johnsen    schedule 22.06.2010
comment
Это, безусловно, самый полезный ответ, когда речь идет о больших файлах. Спасибо. У меня есть репозиторий некоторых PSD-файлов, и раньше для выполнения git gc требовалось гигабайт памяти, теперь требуется менее 100 МБ ОЗУ. Прохладный. - person Albus Dumbledore; 29.10.2016

Git 2.18 (второй квартал 2018 г.) улучшит потребление памяти gc.
До версии 2.18 " git pack-objects" должен выделять массу "struct object_entry" при выполнении своей работы: уменьшение его размера немного повышает производительность.
Это влияет на git gc.

См. commit f6a5576, коммит 3b13a5f, , коммит ac77d0c, коммит 27a7d06, зафиксировать 660b373, зафиксировать 0cb3c14, зафиксировать 898eba5, зафиксировать 43fa44f , коммит 06af3bb, коммит b5c0cbd, , коммит fd9b1ba, зафиксировать 8d6ccce, коммит 4c2db93 (14 апреля 2018 г.), автор Нгуен Тай Нгок Зуй (pclouds).
(объединено Хунио С Хамано -- gitster -- в коммит ad635e8, 23 мая 2018 г.)

pack-objects: переупорядочить участников, чтобы они уменьшились struct object_entry

Предыдущие патчи оставляли в этой структуре много дыр и дополнений.
Этот патч изменяет порядок элементов и уменьшает структуру до 80 байт (со 136 байт в 64-разрядных системах до того, как будет выполнено сжатие полей) с 16 битами в запасе. (и еще пару в in_pack_header_size, когда у нас действительно закончатся биты).

Это последний из серии исправлений для сокращения памяти (см. "pack-objects: немного документа о struct object_entry" для первого).

В целом они уменьшили размер памяти для перепаковки на linux-2.6.git с 3,747 ГБ до 3,424 ГБ, или примерно на 320 МБ, то есть на 8,5 %.
Время выполнения перепаковки не изменилось на протяжении всей этой серии.
Эвар тестирует на большой монорепозиторий, к которому у него есть доступ (больше, чем linux-2.6.git), показал снижение на 7,9%, поэтому общее ожидаемое улучшение должно составить где-то около 8%.


В Git 2.20 (четвертый квартал 2018 г.) будет проще проверять объект, который существует в одном ответвлении, не превращается в дельту по сравнению с другим объектом, который не появляется в том же ответвленном репозитории.

См. коммит fe0ac2f, коммит 108f530, Christian Couder (chriscool).
Помощь: Джефф Кинг (peff) и Дуй Нгуен (pclouds).
См. commit 9eb0986, коммит 16d75fa, коммит 28b8a73, noreferrer18b8a73 a> (16 августа 2018 г.), Джефф Кинг (peff).
Помощь: Джефф Кинг (peff) и Duy Nguyen (pclouds).
(Объединено Junio ​​C Hamano -- gitster - – в commit f3504ea, 17 сентября 2018 г.)

pack-objects: переместите 'layer' в 'struct packing_data'

Это уменьшает размер struct object_entry с 88 байт до 80 и, следовательно, делает упаковку объектов более эффективной.

Например, в репозитории Linux с 12 миллионами объектов git pack-objects --all требуется дополнительная память на 96 МБ, даже если функция слоя не используется.


Обратите внимание, что Git 2.21 (февраль 2019 г.) исправляет небольшую ошибку: «git pack-objects» неправильно использовал неинициализированный мьютекс, который был исправлен.

См. коммит edb673c, коммит 459307b (25 января 2019 г.), автор Патрик Хогг ( ``).
Помощь: Юнио С Хамано (gitster).
(Объединено Junio ​​C Hamano -- gitster -- в commit d243a32, 5 февраля 2019 г.)

pack-objects: переместить мьютекс чтения в структуру packing_data

ac77d0c ("pack-objects: уменьшить поле размера в структуре object_entry", 2018-04-14 ) добавлено дополнительное использование read_lock/read_unlock в недавно представленном oe_get_size_slow для безопасности потоков при параллельных вызовах try_delta().
К сожалению, oe_get_size_slow также используется в последовательном коде, некоторые из которых вызываются перед первым вызовом ll_find_deltas.
Таким образом, инициализация мьютекса чтения не гарантируется.

Решите эту проблему, переместив мьютекс чтения в packing_data и инициализировав его в prepare_packing_data, который инициализируется в cmd_pack_objects.


Git 2.21 (февраль 2019 г.) по-прежнему находит другой способ уменьшить размер пакета с помощью «git pack-objects», изучающего другой алгоритм для вычисления набора объектов для отправки, который обменивает полученный пакетный файл, чтобы сэкономить затраты на обход в пользу небольших толчков.

pack-objects: создать настройку pack.useSparse

Флаг '--sparse' в 'git pack-objects' изменяет алгоритм, используемый для перечисления объектов, на более быстрый для отдельных пользователей, добавляющих новые объекты, которые изменяют только небольшой конус рабочего каталога.
Разреженный алгоритм не рекомендуется для сервера. , который, вероятно, отправляет новые объекты, которые появляются во всем рабочем каталоге.

Создайте параметр "pack.useSparse", который включает этот новый алгоритм.
Это позволит "git push" использовать этот алгоритм без передачи флага "--sparse" на всех четырех уровнях вызовов run_command().

Если установлен флаг «--no-sparse», этот параметр конфигурации переопределяется.

документация пакета конфигурации теперь включает :

pack.useSparse:

Если задано значение true, Git по умолчанию будет использовать параметр "--sparse" в параметре "git pack-objects", если присутствует параметр "--revs".
Этот алгоритм обходит только деревья, которые появляются на путях, вводящих новые объекты.

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

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

Конкретную иллюстрацию см. в разделе "git push работает очень медленно для огромного репо".


Примечание: как было сказано в Git 2.24, такая настройка, как pack.useSparse, все еще является экспериментальной.

См. коммит aaf633c, коммит c6cc4c5, Деррик Столи (derrickstolee).
(Объединено Junio ​​C Hamano -- gitster -- в commit f4f8dfe, 9 сентября 2019 г.)< / суп>

repo-settings: создать настройку feature.experimental

Параметр "feature.experimental" включает параметры конфигурации, которые не должны стать значениями по умолчанию, но требуют дополнительного тестированияg.

Обновите следующие параметры конфигурации, чтобы принять новые значения по умолчанию и использовать структуру repo_settings, если она еще не используется:

  • 'pack.useSparse=истина'
  • 'fetch.negotiationAlgorithm=пропуск'

В Git 2.26 (1 квартал 2020 г.) метод «git pack-objects» повторно использует сохраненные объекты. в существующем пакете для генерации его результата было улучшено.

См. commit d2ea031, зафиксировать 92fb0db, Джефф Кинг (peff).< br> (Объединено Junio ​​C Hamano -- gitster -- в commit a14aebe, 14 февраля 2020 г.)

pack-objects: улучшение частичного повторного использования файла пакета.

При содействии: Джонатан Тан
Подпись: Джефф Кинг
Подпись: Кристиан Кудер

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

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

Одна сложность заключается в том, что если мы опускаем некоторые объекты, мы не можем установить дельту для базы, которую мы не отправляем. Итак, мы должны проверить каждый объект в try_partial_reuse(), чтобы убедиться, что у нас есть его дельта.

Что касается производительности, в худшем случае у нас может быть чередование объектов, которые мы отправляем или не отправляем, и у нас будет столько же фрагментов, сколько и объектов. Но на практике мы отправляем большие куски.

Например, при упаковке torvalds/linux на серверах GitHub теперь повторно использовалось 6,5 млн объектов, но требовалось всего около 50 тыс. фрагментов.

person VonC    schedule 25.05.2018