Шляхи покращення продуктивності стану git


80

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

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

Чи допоможуть підмодулі чи будь-які інші концепції, такі як розбиття репо на менші? Якщо так, то що найкраще для розподілу більшого репо. Чи є інший спосіб покращити час, необхідний для команд git у великому репо?


2
NFS - це майже вузьке місце тут. lstat є досить синхронною операцією.
user611775

Відповіді:


45

Якщо бути точнішим, git залежить від ефективності lstat(2)системного виклику, тож налаштуйте "тайм-аут кешу атрибутів" вашого клієнта може допомогти.

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

Альтернативою, як ви пропонуєте, є зменшення розміру вашого замовлення (розмір пакувальних файлів тут насправді не входить у гру). Варіанти - розріджена оплата, підмодулі або інструмент репо Google .

(Існує потік списку розсилки про використання Git з NFS , але він не відповідає на багато питань.)


31
Те, що ви пропустили: там виправлення Лінуса насправді було об’єднано, і його можна ввімкнути, встановивши core.preloadindexзначення true - див. git-configДокументацію, щоб отримати докладніший опис. (На моєму робочому місці використовується NFS, і я зіткнувся саме з цією проблемою, але ніколи не помічав налаштувань preloadindex. Дякую, що вказали мені правильний шлях!)
Cascabel

1
'До прийнятої відповіді тут слід додати' git config core.preloadindex true '. можливо з прапором -uno від користувача1077329
ostler.c

2
core.preloadindexза замовчуванням прапорець встановлений у true, починаючи з Git 2.1.0: git.kernel.org/pub/scm/git/git.git/tree/Documentation/RelNotes/…
Петр Газаров

38

Я також бачу цю проблему у великому проекті, який передається через NFS.

Мені знадобився деякий час, щоб виявити прапор -uno, який можна присвоїти як git коміту , так і git статусу.

Цей прапор відключає пошук файлів, що не відслідковуються. Це значно зменшує кількість операцій nfs. Причина полягає в тому, що для того, щоб git знаходив відстежувані файли, він повинен шукати у всіх підкаталогах, тому якщо у вас багато підкаталогів, це вам зашкодить. Відключивши git від пошуку невідстежених файлів, ви усуваєте всі ці операції NFS.

Поєднавши це з прапором core.preloadindex, ви зможете отримати резонансну ефективність навіть на NFS.


Як згадується в git-status (1), його можна встановити за замовчуванням, встановивши status.showUntrackedFilesконфігурацію.
johankj

33

Спробуйте git gc . Крім того, git clean може допомогти.

ОНОВЛЕННЯ - Не впевнений, звідки взявся голос проти, але в посібнику Git конкретно зазначено:

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

Користувачам рекомендується регулярно запускати це завдання в кожному сховищі, щоб забезпечити належне використання дискового простору та хорошу експлуатаційну продуктивність.

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

ОНОВЛЕННЯ II - Не впевнений, як я пропустив це, але OP вже спробував git gcіgit clean . Клянусь, цього спочатку там не було, але я не бачу жодних змін у редагуваннях. Вибачте за це!


5
Я також не розумію голосування проти; це дійсно корисно. git gcскоротити час git logбігу з 15 секунд до 0 в одному з моїх репозиторіїв.
GreenRaccoon23,

@NicolasC Ах! Не впевнений, як я це пропустив, але я б також проголосував свою відповідь за це. : - /
Jabari

1
git cg - це добре, git clean може видалити якийсь непотрібний файл?
Лука Регеллін,

18

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

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

Ви втратите зручність нагадування про те, що в будь-якому з підмодулів відбуваються нестадійні зміни, про які ви, можливо, забули, але ви все одно збережете основну зручність знання, коли підмодулі не синхронізуються з основним репо. Крім того, ви все ще можете змінити свій робочий каталог на сам підмодуль і використовувати git-статус у ньому, як зазвичай, щоб побачити більше інформації. Докладніше про те, що означає "брудний", див. У цьому питанні .


7

Ефективність git-статусу повинна покращитися завдяки Git 2.13 (Q2 2017).

Див. Коміт 950a234 (14 квітня 2017 р.) Джеффа Хостелера ( jeffhostetler) .
(Об’єднано Junio ​​C Hamano - 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Тхая Нгюка Дуя ( ) .
(Об’єднано 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() , ми перевірити наявність об'єктного файлу , щоб побачити , якщо ми повинні ставитися до фіксації , як розібраний. Результат - встановити біт "синтаксичний аналіз" для коміту.

Змініть умову, щоб перевірити лише, 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 2.24 (Q3 2019) пропонує ще один параметр для підвищення git statusпродуктивності:

Див. Коміт aaf633c , коміт c6cc4c5 , коміт ad0fb65 , коміт 31b1de6 , коміт b068d9a , коміт 7211b9e (13 серпня 2019 р.) Деррік Столі ( derrickstolee) .
(Об’єднано Junio ​​C Hamano - gitster- у комітеті f4f8dfe , 09 вересня 2019 р.)

repo-settings: створити feature.manyFiles налаштування

feature.manyFilesУстановка підходить для угод РЕПО з великою кількістю файлів в робочому каталозі.
Встановивши index.version=4та core.untrackedCache=true, такі команди, як ' git status', повинні покращитися.

Але:

З Git 2.24 (Q4 2019), шлях до коду, який читає index.versionконфігурацію, був порушений під час нещодавнього оновлення, яке було виправлено.

Див. Коміт c11e996 (23 жовтня 2019 р.) Дерріка Столі ( derrickstolee) .
(Об’єднано Junio ​​C Hamano - gitster- у комітеті 4d6fb2b , 24 жовтня 2019)

repo-settings: прочитати int для index.version

Підписав: Деррік Столі

Кілька параметрів конфігурації були об'єднані в repo_settingsструктуру в ds / feature-macros, включаючи переміщення налаштування конфігурації "index.version" у 7211b9e (" repo-settings: консолідація деяких налаштувань конфігурації", 2019-08-13, Git v2.24.0-rc1 - злиття, зазначене в партії №0 ).

На жаль, цей файл виглядав багато як шаблон, і що, безумовно, є фактором перевантаження copy-paste, налаштування конфігурації аналізується repo_config_ge_bool()замістьrepo_config_get_int() . Це означає, що параметр "index.version = 4" не буде реєструватися належним чином і повернеться до версії 3 за замовчуванням.

Я зрозумів це, включивши v2.24.0-rc0 до кодової бази VFS для Git, де нам дуже важливо, щоб індекс був у версії 4.

Це не було виявлено кодовою базою, оскільки перевірки версій, розміщені в t1600-index.sh, недостатньо перевіряли "базовий" сценарій. Тут ми модифікуємо тест, щоб включити ці звичайні налаштування, щоб не замінити їх на features.manyFilesабо GIT_INDEX_VERSION.
Хоча "типовою" версією є 3, вона знижується до версії 2, do_write_index()коли це не потрібно.


Див. Також stackoverflow.com/a/43667992/6309 та нові index.threadsналаштування конфігурації
VonC

GIT_TRACE = true git log Ось як ви запускаєте трасування і знаходите вузьке місце
dhavale

@dhavale На насправді, так як Git .22, у вас є також trace2: stackoverflow.com/a/56094711/6309
VonC

4

git config --global core.preloadIndex true

Зробив роботу за мене. Ознайомтеся з офіційною документацією тут .


Яку версію Git ви використовуєте?
VonC

2.7.4. Я використовую підсистему Linux для Windows, і навіть в оновленій, apt-getсхоже, є посилання на досить старі пакети.
klimat

1
Гаразд, має сенс. Я не думаю, що це потрібно для більш пізньої версії.
VonC

Це навіть допомогло мені з git версією 2.17.1
Markus Zeller

1

У нашій кодовій базі, де ми маємо десь в межах 20 - 30 підмодулів,
git status --ignore-submodules
різко пришвидшилося для мене. Зверніть увагу, що це не буде повідомляти про стан підмодулів .


1

Щось, про що ще не згадувалося, - це активувати кеш файлової системи на машинах Windows (файлові системи Linux повністю різні, і git був оптимізований для них, тому це, мабуть, допомагає лише у Windows).

git config core.fscache true


В крайньому випадку, якщо git все ще повільний, можна відключити перевірку часу модифікації, тому git повинен з'ясувати, які файли змінилися.

git config core.ignoreStat true

АЛЕ: Змінені файли згодом повинен додати сам розробник за допомогою git add. Git не знаходить змін самостійно.

джерело


Це допомогло мені в Windows 10, хоча я мав досить недавню версію Git для Windows. Дякую. Мій репо склав ~ 100 Гб у папці .git (git lfs)
Алекс Сороколетов

0

Залишки 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цього git читав усі мої великі файли там mmap. Зазвичай цього не роблять, зазвичай statдостатньо.

Я погуглив проблему і виявив проблему використання index та 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та видаліть залишки.


0

Це досить давнє запитання. Хоча, я здивований, що ніхто не коментував двійковий файл, враховуючи розмір сховища.

Ви згадали, що ваше репозиторій 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 від повторного введення файлу.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.