Façons d'améliorer les performances de l'état git
J'ai un repo de 10 Go sur une machine Linux qui est sur NFS. La première fois git status
prend 36 minutes et la suivante git status
prend 8 minutes. Semble que Git dépend du système d'exploitation pour la mise en cache des fichiers. Seules les premières commandes git
comme commit
, status
cela implique pack / remballer l'ensemble du repo prend beaucoup de temps pour un énorme repo. Je ne suis pas sûr si vous avez utilisé git status
sur une telle grande repo, mais quelqu'un a rencontré ce problème?
, j'ai essayé git gc
, git clean
, git repack
mais le temps est toujours/presque la même.
Les sous-modules ou tout autre concept comme casser le repo en plus petits aideront-ils? Si oui, quel est le meilleur pour diviser un repo plus grand. Est-il un autre moyen d'améliorer le temps pris pour les commandes git sur un grand repo?
7 réponses
Pour être plus précis, git dépend de l'efficacité de la lstat(2)
appel système, afin de peaufiner votre client "attribut délai d'expiration du cache" pourrait faire l'affaire.
Le manuel de git-update-index
- essentiellement un mode manuel pour git-status
- décrit ce que vous pouvez faire pour atténuer cela, en en utilisant l'indicateur --assume-unchanged
pour supprimer son comportement normal et mettre à jour manuellement les chemins que vous avez modifiés. Vous pouvez même programmer votre éditeur pour désactiver cet indicateur chaque fois que vous enregistrez un fichier.
Le alternative, comme vous le suggérez, est de réduire la taille de votre caisse (la taille des fichiers Pack n'entre pas vraiment en jeu ici). Les options sont un checkout clairsemé, des sous-modules ou L'outil repo de Google.
(Il existe une liste de diffusion sur l'utilisation de Git avec NFS , mais elle ne répond pas à beaucoup de questions.)
Je vois aussi ce problème sur un grand projet partagé sur NFS.
Il m'a fallu du temps pour découvrir le drapeau - uno qui peut être donné à la fois à git commit et à git status.
Ce que fait cet indicateur est de désactiver la recherche de fichiers non suivis. Cela réduit considérablement le nombre d'opérations nfs. La raison en est que pour que git découvre des fichiers non suivis, il doit regarder dans tous les sous-répertoires, donc si vous avez beaucoup de sous-répertoires, cela vous blessera. En désactivant git de la recherche de fichiers non suivis, vous éliminez toutes ces opérations NFS.
Combinez ceci avec le noyau.drapeau preloadindex et vous pouvez obtenir resonable perfomance même sur NFS.
Essayez git gc . Aussi, git propre peut - aider.
UPDATE - Je ne sais pas d'où vient le vote négatif, mais le manuel git indique spécifiquement:
Exécute un certain nombre de tâches de maintenance dans le référentiel actuel, telles que la compression des révisions de fichiers (pour réduire augmenter les performances) et en supprimant les objets inaccessibles qui peuvent avoir été créés à partir d'invocations antérieures de git add.
Les utilisateurs sont encouragé à exécuter cette tâche sur une base régulière dans chaque référentiel pour maintenir une bonne utilisation de l'espace disque et de bonnes performances d'exploitation.
Je remarque toujours une différence après avoir exécuté git gc lorsque le statut git est lent!
UPDATE II - Je ne sais pas comment j'ai manqué cela, mais L'OP a déjà essayé git gc et git clean. Je jure que ce n'était pas là à l'origine, mais je ne vois aucun changement dans les modifications. Désolé pour ça!
Si votre repo git utilise beaucoup de sous-modules, vous pouvez grandement accélérer les performances de git status en éditant le fichier de configuration dans le .répertoire git et Paramètre ignore = dirty
sur tous les sous-modules particulièrement grands / lourds. Par exemple:
[submodule "mysubmodule"]
url = ssh://mysubmoduleURL
ignore = dirty
Vous perdrez la commodité d'un rappel qu'il y a des changements non indexés dans l'un des sous-modules que vous avez peut-être oublié, mais vous conserverez toujours la commodité principale de savoir quand les sous-modules sont désynchronisés avec le repo principal. De plus, vous pouvez toujours changer votre répertoire de travail pour le sous-module lui-même et utiliser le statut git dans celui-ci comme d'habitude pour voir plus d'informations. Voir cette question pour plus de détails sur ce "sale" signifie.
Les performances de git status devraient s'améliorer avec Git 2.13 (T2 2017).
Voir commettre 950a234 (14 Avril 2017) par Jeff Hostetler (jeffhostetler
).
(Fusionné par Junio C Hamano -- gitster
-- dans commettre 8b6bba6, 24 Avril 2017)
> string-list
: Utilisation ALLOC_GROW
macro lors de la réallocation string_list
Utilisez la macro
ALLOC_GROW()
lors de la réallocation d'un tableaustring_list
plutôt que de simplement l'augmenter de 32.
C'est une performance optimisation.Pendant le statut sur un très grand repo et il y a beaucoup de changements, un pourcentage important du temps d'exécution total est consacré à la réallocation
wt_status.changes
Tableau.Ce changement diminue le temps
wt_status_collect_changes_worktree()
de 125 secondes à 45 secondes sur mon très grand dépôt.
De plus, Git 2.17 (Q2 2018) introduira une nouvelle trace, pour mesurer où le temps est passé dans les opérations indexées.
Voir commit ca54d9b (27 Jan 2018) par Nguynn Thái NGCC Duy (pclouds
).
(Fusionné par Junio C Hamano -- gitster
-- dans commettre 090dbea, 15 Février 2018)
trace
: mesure où le temps est passé dans les opérations indexéesTous les blocs de code lourds connus sont mesurés (à l'exception de la base de données d'objets accès). Cela devrait aider à déterminer si une optimisation est efficace ou pas.
Un statut git non optimisé serait donnez quelque chose comme ci-dessous:
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'
Le même Git 2.17 (Q2 2018) améliore git status
avec:
S'Engager f39a757, s'engager 3ca1897, s'engager fd9b544, s'engager d7d1b49 (09 Jan 2018) par Jeff Hostetler (
jeffhostetler
).
(Fusionné par Junio C Hamano --gitster
-- dans commettre 4094e47, 08 Mar 2018)
"git status
" peut passer beaucoup de cycles pour calculer la relation entre la branche actuelle et son amont, qui peut maintenant être désactivé avec l'option"--no-ahead-behind
".S'Engager ebbed3b (25 Février 2018) par Derrick Stolee (
derrickstolee
).
revision.c
: réduire les requêtes de base de données d'objetsDans
mark_parents_uninteresting()
, nous vérifions l'existence d'une fichier objet pour voir si nous devrions traiter un commit comme analysé. Résultat est de définir le "analysé" peu sur le commettre.Modifiez la condition pour vérifier uniquement
has_object_file()
si résultat changerait le bit analysé.Lorsqu'une branche locale est différente de sa ref amont, "
git status
" va calculer à l'avance/derrière qui compte.
Il utilisepaint_down_to_common()
et frappemark_parents_uninteresting()
.Sur une copie du repo Linux avec une instance locale de "master" derrière la branche distante "
origin/master
"de ~ 60 000 commits, nous trouvons la performance de "git status
" est passé de 1,42 secondes à 1,32 secondes, pour un parent différence de -7,0%.
Je ne sais pas quel sens cela fait, mais pour moi le statut prenait 30 min, j'ai essayé tout ce que je pouvais trouver sur le web, finalement, j'ai fait git reset
j'ai eu 100s de changements que j'ai appliqués de stash où stash a été créé à partir d'une branche différente mais appliqué sur cette branche, ils ont tous été mis en scène mais pas engagés (juste expliquer, ce que j'ai fait différemment avant de rencontrer ce problème), git reset
a pris 15 min mais après que tout a commencé à fonctionner rapidement comme moins d'une seconde pour le statut. Je ne suis pas un git expert juste dire ce qui a obtenu mon problème résolu, j'espère qu'il aide les autres qui atterrissent sur cette page.