Vraag Git is echt traag voor 100.000 objecten. Eventuele oplossingen?


Ik heb een "verse" git-svn repo (11.13 GB) met meer dan 100.000 objecten erin.

Ik heb voorgevormd

git fsck
git gc

op de repo na de eerste checkout.

Ik probeerde toen om een ​​te doen

git status

De tijd die het kost om een ​​git-status uit te voeren is ergens tussen 2m25.578s en 2m53.901s

Ik heb de git-status getest door het commando uit te geven

time git status

5 keer en alle tijden liepen tussen de twee tijden hierboven vermeld.

Ik doe dit op een Mac OS X, lokaal niet via een VM.

Het zou niet lang kunnen duren.

Om het even welke ideeën? Helpen?

Bedankt.

Bewerk

Ik heb een collega die naast me zit met een vergelijkbare doos. Minder RAM en Debian draaien met een jfs-bestandssysteem. Zijn git status draait in .3 op dezelfde repo (het is ook een git-svn-checkout).

Ook heb ik recent mijn bestandspermissies (naar 777) in deze map gewijzigd en dit heeft de tijd aanzienlijk teruggebracht (waarom, ik heb geen idee). Ik kan het nu ergens tussen de 3 en 6 seconden laten doen. Dit is beheersbaar, maar toch een pijn.


49
2017-07-22 22:10


oorsprong


antwoorden:


Het kwam neer op een paar items die ik nu kan zien.

  1. git gc --aggressive
  2. Openen van bestandsrechten voor 777

Er moet iets anders aan de hand zijn, maar dit waren de dingen die duidelijk de grootste impact maakten.


25
2017-07-26 23:03



git status moet elke keer naar elk bestand in de repository kijken. Je kunt het vertellen om te stoppen met kijken naar bomen waar je niet mee bezig bent

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

bron

Van de manpage:

Wanneer deze vlaggen zijn opgegeven, is de   objectnamen die zijn vastgelegd voor de paden   zijn niet bijgewerkt. In plaats daarvan deze   opties instellen en schakel de "aanname uit"   ongewijzigd "bit voor de paden   "veronderstel ongewijzigd" bit is aan, git   stopt met het controleren van de werkende boomstammen   voor mogelijke aanpassingen, dus jij   moet het bit handmatig uitzetten om te vertellen   git wanneer je de werkende boom verandert   het dossier. Dit is soms handig wanneer   werken met een groot project op een   bestandssysteem dat zeer traag lstat heeft (2)   systeemoproep (bijvoorbeeld cif's).

Deze optie kan ook worden gebruikt als een   grof bestandsniveau-mechanisme om te negeren   niet-gecommitteerde wijzigingen in bijgehouden bestanden   (verwant met wat .gitignore doet voor   niet-beluisterde bestanden). Git zal mislukken   (sierlijk) voor het geval dat nodig is   wijzig dit bestand in de index, b.v.   bij het samenvoegen van een commit; dus in   als het veronderstelde-niet-gevonden bestand is   stroomopwaarts veranderd, zul je dit moeten doen   behandel de situatie handmatig.

Veel operaties in git zijn afhankelijk van je   bestandssysteem om een ​​efficiënte te hebben   lstat (2) implementatie, dus dat   st_mtime informatie voor werkboom   bestanden kunnen goedkoop worden gecontroleerd om te zien of   de inhoud van het bestand is veranderd van   de versie opgenomen in de index   het dossier. Helaas zijn sommige bestandssystemen   hebben inefficiënte lstat (2). Als jouw   bestandssysteem is er een van, dat kun je instellen   "veronderstel ongewijzigde" bit om je te paden   zijn niet veranderd om git niet te laten veroorzaken   doe deze controle. Merk op dat dit is ingesteld   bit op een pad betekent niet dat het git wil   controleer de inhoud van het bestand om te zien   als het is veranderd - het maakt naar   laat elke controle weg en ga ervan uit dat deze heeft plaatsgevonden   niet veranderd. Wanneer u wijzigingen aanbrengt in   werkende boomstammen, dat moet   expliciet vertellen Git erover door   drop "veronderstelt ongewijzigd" bit,   ofwel vóór of na je wijziging   hen.

...

Om "veronderstelt ongewijzigd" in te stellen   bit, gebruik -assume-unchanged optie. Naar   niet ingesteld, gebruik - niet veronderstellen - ongewijzigd.

Het commando kijkt naar core.ignorestat   configuratievariabele. Wanneer dit is   waar, paden bijgewerkt met git   update-indexpaden ... en paden bijgewerkt   met andere git-commando's die updaten   zowel index- als werkboom (bijvoorbeeld git   apply --index, git checkout-index -u,   en git read-tree -u) zijn   automatisch gemarkeerd als "aannemen   ongewijzigd. "Let op:" neem aan   ongewijzigd "bit is niet ingesteld als git   update-index --refresh vindt de   werkboombestand komt overeen met de index   (gebruik git update-index - echt vernieuwen   als je ze wilt markeren als "aannemen   ongewijzigd ").


Het is duidelijk dat deze oplossing alleen werkt als er delen van de repo zijn die u gemakkelijk kunt negeren. Ik werk aan een project van vergelijkbare grootte, en er zijn absoluut grote bomen die ik niet regelmatig hoef te controleren. De semantiek van git-status maakt het een algemeen O (n) probleem (n in aantal bestanden). U hebt domeinspecifieke optimalisaties nodig om het beter te doen.

Merk op dat als je in een stikpatroon werkt, dat wil zeggen als je veranderingen van stroomopwaartse integratie integreert door samen te voegen in plaats van rebasen, deze oplossing minder handig wordt, omdat een wijziging in een ongewijzigd -assumeus-ongewijzigd object dat van bovenstrooms wordt samengevoegd een samenvoeging wordt conflict. U kunt dit probleem voorkomen met een rebasing-workflow.


15
2017-07-25 23:45



Een oplossing voor de langere termijn is om intern de status van git naar cache-bestandssysteem te vergroten.

Karsten Blees heeft dit gedaan voor msysgit, wat de prestaties op Windows aanzienlijk verbetert. In mijn experimenten heeft zijn verandering de tijd genomen voor "git-status" van 25 seconden tot 1-2 seconden op mijn Win7-machine die in een VM draait.

Karsten's veranderingen: https://github.com/msysgit/git/pull/94

Discussie over de caching-aanpak: https://groups.google.com/forum/#!topic/msysgit/fL_jykUmUNE/discussion


5
2017-10-17 15:29



git status zou sneller moeten zijn in Git 2.13 (Q2 2017), vanwege:

Op dat laatste punt, zie commit a33fc72 (14 april 2017) door Jeff Hostetler (jeffhostetler).
(Samengevoegd door Junio ​​C Hamano - gitster - in commit cdfe138, 24 apr 2017) 

read-cache: force_verify_index_checksum

Voer git uit om de verificatie van de SHA1-1-controlesom aan het einde van   het indexbestand in verify_hdr() waar vandaan wordt geroepen read_index() Tenzij de "force_verify_index_checksum"globale variabele is ingesteld.

Onderwijzen fsck om deze verificatie af te dwingen.

De controlesomverificatie is voor het detecteren van schijfbeschadiging en voor kleine projecten is de tijd die nodig is om SHA-1 te berekenen niet zo belangrijk, maar voor gigantische opslagplaatsen voegt deze berekening aanzienlijke tijd aan elk commando toe.


Git 2.14 verbetert weer de git-statusprestaties door beter rekening te houden met de "niet-traceerde cache", waarmee Git het lezen van de niet-traceerde mappen kan overslaan als deze stat gegevens zijn niet gewijzigd, met behulp van de mtime veld van de stat structuur.

Zie de Documentation/technical/index-format.txt voor meer informatie over niet-opgeslagen cache.

Zien commit edf3b90 (08 mei 2017) door David Turner (dturner-tw).
(Samengevoegd door Junio ​​C Hamano - gitster - in commit fa0624f, 30 mei 2017) 

Wanneer "git checkout","git merge", enz. manipuleert de in-core index, verschillende delen van informatie in de index-extensies worden verwijderd uit de oorspronkelijke staat, omdat het meestal niet het geval is dat ze up-to-date worden gehouden en synchroon lopen met de bewerking op de hoofdindex.

De niet-traceerde cache-extensie wordt nu over deze bewerkingen gekopieerd, wat de "git-status" zou versnellen (zolang de cache op de juiste manier ongeldig wordt gemaakt).


Meer in het algemeen zal het schrijven naar de cache ook sneller zijn met Git 2.14.x / 2.15

Zien commit ce012de, commit b50386c, commit 3921a0b (21 augustus 2017) door Kevin Willford (``).
(Samengevoegd door Junio ​​C Hamano - gitster - in commit 030faf2, 27 aug. 2017) 

Vroeger spendeerden we meer dan noodzakelijke cycli toewijzen en bevrijden   stukje geheugen tijdens het schrijven van elke indexinvoer.
  Dit is geoptimaliseerd.

[Dat] zou ergens tussen de 3-7% besparen als de index meer dan een miljoen items bevatte zonder prestatieverlies bij kleine repo's.


Update december 2017: Git 2.16 (Q1 2018) zal een extra verbetering voorstellen, deze keer voor git log, omdat de code voor het herleiden van losse objectbestanden net is geoptimaliseerd.

Zien commit 163ee5e (04 dec 2017) door Derrick Stolee (derrickstolee).
(Samengevoegd door Junio ​​C Hamano - gitster - in commit 97e1f85, 13 december 2017) 

sha1_file: gebruik strbuf_add() in plaats van strbuf_addf()

Vervang het gebruik van strbuf_addf() met strbuf_add() bij het opsommen   losse objecten in for_each_file_in_obj_subdir(). Omdat we al   controleer de lengte en hex-waarden van de string alvorens te consumeren   het pad, kunnen we extra berekening voorkomen door het gebruik van de   niveau methode.

Eén consument van for_each_file_in_obj_subdir() is de afkorting   code. OID (object-ID's) afkortingen gebruiken een lijst in de cache van losse objecten (per submap van een object) om herhaalde query's snel te maken, maar dat is zo   significante cache laadtijd wanneer er veel losse objecten zijn.

De meeste repositories hebben niet veel losse objecten voordat ze opnieuw worden ingepakt, maar in de GVFS case (zie "Aankondiging van GVFS (Git Virtual File System)") de repo's kunnen miljoenen losse objecten bevatten.
  Profiel 'git log' profileren in Git voor Windows op een voor GVFS geschikte repo met ~ 2,5 miljoen losse objecten onthulde dat 12% van de CPU-tijd werd besteed in strbuf_addf().

Voeg een nieuwe prestatietest toe aan p4211-line-log.sh dat is meer   gevoelig voor deze cache-laden.
  Door te beperken tot 1000 commits, lijken we meer op wachttijd van gebruikers bij het lezen van geschiedenis in een pager.

Voor een kopie van de Linux-repo met twee ~ 512 MB-pakketbestanden en ~ 572K losse objecten, had het uitvoeren van 'git-log - onlineachter - parents --raw -1000' de volgende prestaties:

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

Update maart 2018: Git 2.17 zal verbeteren git status wat meer: ​​zie dit antwoord.


5
2018-04-27 21:12



Over het algemeen is mijn mac ok met git, maar als er veel losse objecten zijn, wordt het veel langzamer. Het lijkt erop dat hfs niet zo goed is met veel bestanden in een enkele map.

git repack -ad

Gevolgd door

git gc --prune=now

Zal een enkel bestand maken en losse voorwerpen verwijderen. Het kan enige tijd duren om deze uit te voeren.


4
2018-03-06 20:13



Je zou kunnen proberen de --aggressive overschakelen naar git gc en kijk of dat helpt:

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

Ook zou je kunnen gebruiken git filter-branch om oude commits en / of bestanden te verwijderen als je dingen hebt die je niet nodig hebt in je geschiedenis (bijvoorbeeld oude binaire bestanden).


3
2017-07-22 22:12



Voor wat het waard is, vond ik onlangs een grote discrepantie tussen de git status commando tussen mijn meester en dev branches.

Om een ​​lang verhaal kort te maken, heb ik het probleem opgespoord tot een enkel 280 MB-bestand in de hoofdmap van het project. Het was een onopzettelijke controle van een database-dump dus het was goed om het te verwijderen.

Dit is het voor en na:

 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

Ik heb 105.000 objecten in de winkel, maar het lijkt erop dat grote bestanden meer een bedreiging vormen dan veel kleine bestanden.


2
2017-10-02 16:40



Je zou het ook kunnen proberen git repack


1
2017-07-22 22:14



Misschien gebruikt u een virusscanner? Ik heb hier een aantal grote projecten getest op Windows en Linux - het was verdomd snel!

Ik denk niet dat je een git gc in een gekloonde repo moet doen (het zou schoon moeten zijn).

Is je harde schijf OK? IOPS en R / W per seconde? Misschien is het beschadigd?


0
2017-07-22 22:14



misschien probeert schijnwerper de bestanden te indexeren. Misschien zet je schijnwerpers uit voor je code. Controleer Activity Monitor en kijk welke processen draaien.


0
2017-07-22 22:26