web-dev-qa-db-fra.com

Comment améliorer les performances du statut git

J'ai un dépôt de 10 Go sur une machine Linux qui est sur NFS. La première fois git status prend 36 minutes et git status prend 8 minutes. Il 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 qui impliquent de compresser/remballer l'ensemble du référentiel prennent très longtemps pour un énorme référentiel. Je ne sais pas si vous avez utilisé git status sur une telle pension, mais quelqu'un a-t-il rencontré ce problème?

J'ai essayé git gc, git clean, git repack mais le temps pris est toujours/presque le même.

Est-ce que les sous-modules ou d'autres concepts comme la division du dépôt en plus petits seront utiles? Si tel est le cas, quel est le meilleur moyen de fractionner un dépôt plus important. Existe-t-il un autre moyen d'améliorer le temps nécessaire aux commandes git sur un grand dépôt?

67
Senthil A Kumar

Pour être plus précis, git dépend de l'efficacité de l'appel système lstat(2), donc peaufiner "timeout cache 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 y remédier, en en utilisant le --assume-unchanged flag 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 ce drapeau à chaque fois que vous enregistrez un fichier.

L’alternative, comme vous le suggérez, est de réduire la taille de votre paiement (la taille des fichiers de paquets n’entre pas vraiment en jeu ici). Les options sont une caisse creuse, des sous-modules ou l'outil repo de Google.

(Il existe une liste de diffusion discussion sur l'utilisation de Git avec NFS , mais elle ne répond pas à de nombreuses questions.)

40
Josh Lee

Je vois également ce problème sur un grand projet partagé sur NFS.

Il m'a fallu un certain temps pour découvrir l'indicateur - uno qui peut être attribué à la fois à git commit et à git status.

Ce que cet indicateur fait 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 puisse découvrir des fichiers non suivis, il doit regarder dans tous les sous-répertoires, donc si vous avez plusieurs sous-répertoires, cela vous blessera. En désactivant git de rechercher des fichiers non suivis, vous éliminez toutes ces opérations NFS.

Combinez cela avec l'indicateur core.preloadindex et vous pouvez obtenir des performances résonnables même sur NFS.

32
user1077329

Essayez git gc . Aussi, git clean mai aide.

[~ # ~] mise à jour [~ # ~] - Je ne sais pas d'où vient le vote négatif, mais le manuel de git indique spécifiquement:

Exécute un certain nombre de tâches de gestion interne dans le référentiel actuel, telles que la compression des révisions de fichiers (pour réduire l'espace disque et augmenter les performances) et supprimer les objets inaccessibles qui peuvent avoir été créés à partir d'appels antérieurs de git add.

Les utilisateurs sont encouragés à exécuter cette tâche régulièrement dans chaque référentiel pour maintenir une bonne utilisation de l'espace disque et de bonnes performances de fonctionnement.

Je remarque toujours une différence après avoir exécuté git gc lorsque le statut de git est lent!

MISE À JOUR II - Je ne sais pas comment j'ai raté 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é!

27
Jabari

Si votre dépôt git fait un usage intensif des sous-modules, vous pouvez considérablement accélérer les performances de l'état git en modifiant le fichier de configuration dans le répertoire .git et en définissant ignore = dirty sur tout sous-module particulièrement grand/lourd. Par exemple:

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

Vous perdrez la commodité d'un rappel qu'il y a des changements non programmé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 ne sont pas synchronisés avec le référentiel principal. De plus, vous pouvez toujours changer votre répertoire de travail en sous-module lui-même et utiliser l'état git à l'intérieur comme d'habitude pour voir plus d'informations. Voir cette question pour plus de détails sur ce que signifie "sale".

16
beno

Les performances du statut git devraient s'améliorer avec Git 2.13 (T2 2017).

Voir commit 950a234 (14 avril 2017) par Jeff Hostetler (jeffhostetler) .
(Fusionné par Junio ​​C Hamano - gitster - in commit 8b6bba6 , 24 avr 2017)

> string-list: Utilisez macro ALLOC_GROW lors de la réaffectation string_list

Utilisez la macro ALLOC_GROW() lors de la réaffectation d'un tableau string_list Plutôt que de simplement l'augmenter de 32.
Il s'agit d'une optimisation des performances.

Lors de l'état sur un référentiel très volumineux et de nombreuses modifications, un pourcentage important du temps d'exécution total est consacré à la réaffectation du wt_status.changes Tablea .

Ce changement diminue le temps en wt_status_collect_changes_worktree() de 125 secondes à 45 secondes sur mon très grand référentiel.


De plus, Git 2.17 (Q2 2018) introduira une nouvelle trace, pour mesurer où le temps est passé dans les opérations lourdes d'index.

Voir commit ca54d9b (27 janvier 2018) par Nguyễn Thái Ngọc Duy (pclouds) .
(Fusionné par Junio ​​C Hamano - gitster - in commit 090dbea , 15 février 2018)

trace: mesure où le temps est passé dans les opérations lourdes d'index

Tous les blocs de code lourds connus sont mesurés (sauf l'accès à la base de données d'objets). Cela devrait permettre d'identifier si une optimisation est efficace ou non.
Un statut git non optimisé donnerait 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:

revision.c: Réduire les requêtes de base de données d'objets

Dans mark_parents_uninteresting(), nous vérifions l'existence d'un fichier objet pour voir si nous devons traiter un commit comme analysé. Le résultat est de définir le bit "analysé" sur la validation.

Modifiez la condition pour vérifier uniquement has_object_file() si le résultat changerait le bit analysé.

Lorsqu'une branche locale est différente de sa référence amont, "git status" Calculera les décomptes avant/arrière.
Ceci utilise Paint_down_to_common() et frappe mark_parents_uninteresting().

Sur une copie du dépôt Linux avec une instance locale de "master" derrière la branche distante "Origin/master" De ~ 60 000 commits, nous constatons que les performances de "git status" Sont passées de 1,42 seconde à 1,32 seconde, pour une différence relative de -7,0%.

7
VonC

git config --global core.preloadIndex true

A fait le travail pour moi. Consultez la documentation officielle ici .

2
klimat

Dans notre base de code où nous avons quelque part dans la gamme de 20 à 30 sous-modules,
git status --ignore-submodules
a accéléré considérablement les choses pour moi. Notez que ceci ne rendra pas compte de l'état des sous-modules.

1
citysurrounded

Je ne sais pas quel sens cela fait, mais pour moi, le statut prenait 30 minutes, j'ai essayé tout ce que je pouvais trouver sur le Web, enfin, j'ai fait git reset J'ai eu des centaines de changements que j'ai appliqués à partir de stash où le 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 validés (expliquant simplement ce que j'ai fait différemment avant de rencontrer ce problème), git reset a pris 15 minutes mais après cela, tout a commencé à fonctionner rapidement comme moins d'une seconde pour le statut. Je ne suis pas un expert git qui dit simplement ce qui a résolu mon problème, j'espère que cela aidera les autres qui atterriront sur cette page.

0
Vivek

Quelque chose qui n'a pas encore été mentionné est d'activer le cache du système de fichiers sur les machines Windows (les systèmes de fichiers Linux sont complètement différents et git a été optimisé pour eux, donc cela n'aide probablement que sur Windows).

git config core.fscache true

git config core.ignoreStat true

MAIS: Les fichiers modifiés doivent être ajoutés ensuite par le développeur lui-même avec git add. Git ne trouve pas de changements lui-même.

source

0
dCSeven