English ▾ Themen ▾ Neueste Version ▾ gitpacking zuletzt aktualisiert in 2.46.0

NAME

gitpacking - Fortgeschrittene Konzepte im Zusammenhang mit dem Packen in Git

SYNOPSIS

gitpacking

BESCHREIBUNG

Dieses Dokument beschreibt einige fortgeschrittene Konzepte im Zusammenhang mit dem Packen in Git.

Viele Konzepte werden derzeit verstreut in Handbuchseiten verschiedener Git-Befehle beschrieben, einschließlich git-pack-objects[1], git-repack[1] und andere, sowie gitformat-pack[5] und Teile des Documentation/technical-Verzeichnisses.

Es gibt viele Aspekte des Packens in Git, die in diesem Dokument nicht behandelt werden und stattdessen in den oben genannten Bereichen zu finden sind. Im Laufe der Zeit können diese verstreuten Bits in diesem Dokument zusammengeführt werden.

Pseudo-Merge-Bitmaps

Hinweis
Pseudo-Merge-Bitmaps gelten als experimentelles Feature, daher können sich Konfiguration und viele Ideen ändern.

Hintergrund

Erreichbarkeits-Bitmaps sind am effizientesten, wenn wir auf der Festplatte gespeicherte Bitmaps für einen oder mehrere der Startpunkte einer Traverse haben. Aus diesem Grund speichert Git vorzugsweise Bitmaps für Commits an den Spitzen von Refs, da Traversen tendenziell mit diesen Punkten beginnen.

Aber wenn Sie eine große Anzahl von Refs haben, ist es nicht praktikabel, eine Bitmap für jeden Ref-Tipp zu speichern. Das beansprucht Speicherplatz und das bloße ODERn all dieser Bitmaps ist teuer.

Eine Möglichkeit, damit umzugehen, besteht darin, Bitmaps zu erstellen, die Gruppen von Refs darstellen. Wenn eine Traverse die gesamte Gruppe abfragt, können wir diese einzelne Bitmap verwenden, anstatt jede Ref einzeln zu betrachten. Da diese Bitmaps die Menge der Objekte darstellen, die in einem hypothetischen Merge aller Commits erreichbar wären, nennen wir sie Pseudo-Merge-Bitmaps.

Übersicht

Eine "Pseudo-Merge-Bitmap" bezieht sich auf ein Paar von Bitmaps, wie folgt:

Commit-Bitmap

Eine Bitmap, deren gesetzte Bits die Menge der Commits beschreiben, die in der "Merge"-Bitmap des Pseudo-Merges enthalten sind (wie unten).

Merge-Bitmap

Eine Bitmap, deren gesetzte Bits die Erreichbarkeits-Closure über die Menge der Commits in der "Commits"-Bitmap des Pseudo-Merges beschreiben (wie oben). Eine identische Bitmap würde für einen Octopus-Merge mit der gleichen Menge von Eltern wie in der Commit-Bitmap beschrieben generiert werden.

Pseudo-Merge-Bitmaps können Bitmap-Traversen beschleunigen, wenn alle Commits für einen gegebenen Pseudo-Merge auf einer Seite der Traverse aufgeführt sind, entweder direkt (durch explizite Abfrage als Teil von HAVES oder WANTS) oder indirekt (durch Begegnung während einer Fill-in-Traverse).

Anwendungsfälle

Angenommen, es existiert eine Pseudo-Merge-Bitmap mit einer großen Anzahl von Commits, die alle in der WANTS-Sektion einer Bitmap-Traversierungsabfrage aufgeführt sind. Wenn Pseudo-Merge-Bitmaps aktiviert sind, kann die Bitmap-Maschinerie schnell feststellen, dass ein Pseudo-Merge existiert, der eine Teilmenge der gewünschten Objekte auf einer Seite der Abfrage erfüllt. Dann können wir die EWAH-komprimierte Bitmap aufblasen und sie in die Ergebnis-Bitmap einfügen. Im Gegensatz dazu müssten wir ohne Pseudo-Merge-Bitmaps den Dekompressions- und OR-Schritt für eine potenziell große Anzahl einzelner Bitmaps wiederholen, was proportional mehr Zeit beanspruchen kann.

Ein weiterer Vorteil von Pseudo-Merges ergibt sich, wenn eine Kombination aus (a) einer großen Anzahl von Referenzen, (b) schlechter Bitmap-Abdeckung und (c) tiefen, verschachtelten Bäumen vorliegt, was die Fill-in-Traverse relativ teuer macht. Angenommen, es gibt eine ausreichend große Anzahl von Tags, bei denen das Bitmapping jedes Tags einzeln nicht machbar ist. Ohne Pseudo-Merge-Bitmaps würde die Berechnung des Ergebnisses von z.B. git rev-list --use-bitmap-index --count --objects --tags wahrscheinlich eine große Menge an Fill-in-Traverse erfordern. Aber wenn eine große Menge dieser Tags zusammen in einer Pseudo-Merge-Bitmap gespeichert ist, kann die Bitmap-Maschinerie die Tatsache nutzen, dass wir nur an der Vereinigung der von all diesen Tags erreichbaren Objekte interessiert sind, und die Abfrage viel schneller beantworten.

Konfiguration

Referenzspitzen werden gemäß zwei Kriterien in verschiedene Pseudo-Merge-Gruppen eingeteilt. Ein Referenzname entspricht einem oder mehreren der definierten Pseudo-Merge-Muster und optional einem oder mehreren Erfassungsgruppen innerhalb dieses Musters, die die Gruppe weiter unterteilen.

Innerhalb einer Gruppe können Commits je nach ihrem Alter als "stabil" oder "instabil" betrachtet werden. Dies wird durch Setzen der Konfigurationswerte bitmapPseudoMerge.<name>.stableThreshold und bitmapPseudoMerge.<name>.threshold gesteuert.

Alle stabilen Commits werden in Pseudo-Merge-Gruppen gleicher Größe (bitmapPseudoMerge.<name>.stableSize) zusammengefasst. Wenn die Konfiguration stableSize beispielsweise auf 100 gesetzt ist, bilden die ersten 100 Commits (sortiert nach Commit-Datum), die älter als der Wert stableThreshold sind, eine Gruppe, die nächsten 100 Commits eine weitere Gruppe und so weiter.

Bei instabilen Commits versucht die Pseudo-Merge-Maschinerie, ältere Commits zu großen Gruppen zu kombinieren, im Gegensatz zu neueren Commits, die in kleineren Gruppen erscheinen. Dies basiert auf der Heuristik, dass Referenzen, deren Tipp-Commit älter ist, seltener geändert werden, um auf einen anderen Commit zu zeigen, als eine Referenz, deren Tipp-Commit neuer ist.

Die Größe der Gruppen wird durch eine Potenzgesetz-Zerfallsfunktion bestimmt, und der Zerfallsparameter entspricht ungefähr "k" in f(n) = C*n^(-k/100), wobei f(n) die Größe der n-ten Pseudo-Merge-Gruppe beschreibt. Die Abtastrate steuert, welcher Prozentsatz der berechtigten Commits als Kandidaten betrachtet wird. Der Schwellenwert gibt das Mindestalter an (um zu junge Commits von der Aufnahme in eine Pseudo-Merge-Gruppe auszuschließen, was sie weniger gültig macht). Der Parameter "maxMerges" legt eine Obergrenze für die Anzahl der Pseudo-Merge-Commits fest, die eine einzelne Gruppe

Die "stable"-bezogenen Parameter steuern "stabile" Pseudo-Merge-Gruppen, die aus einer festen Anzahl von Commits bestehen, die älter als der konfigurierte "stable threshold"-Wert sind und in Blöcken von "stableSize" nach Alter gruppiert werden können.

Die genaue Konfiguration für Pseudo-Merges lautet wie folgt:

Hinweis
Die Konfigurationsoptionen in bitmapPseudoMerge.* gelten als EXPERIMENTELL und können sich ändern oder in Zukunft vollständig entfernt werden. Weitere Informationen zur Pseudo-Merge-Bitmap-Funktion finden Sie im Abschnitt "Pseudo-Merge-Bitmaps" von gitpacking[7].
bitmapPseudoMerge.<name>.pattern

Regulärer Ausdruck, der verwendet wird, um Referenznamen abzugleichen. Commits, auf die von Referenzen gezeigt wird, die diesem Muster entsprechen (und die unten genannten Kriterien erfüllen, wie bitmapPseudoMerge.<name>.sampleRate und bitmapPseudoMerge.<name>.threshold), werden für die Aufnahme in eine Pseudo-Merge-Bitmap berücksichtigt.

Commits werden in Pseudo-Merge-Gruppen gruppiert, basierend darauf, ob eine oder mehrere Referenzen, die auf einen bestimmten Commit zeigen, mit dem Muster übereinstimmen, einem erweiterten regulären Ausdruck.

Innerhalb einer Pseudo-Merge-Gruppe können Commits weiter in Untergruppen gruppiert werden, basierend auf den Erfassungsgruppen im Muster. Diese Untergruppierungen werden aus den regulären Ausdrücken gebildet, indem alle Erfassungsgruppen aus dem regulären Ausdruck verkettet werden, mit einem - Bindestrich dazwischen.

Wenn das Muster beispielsweise refs/tags/ lautet, werden alle Tags (vorausgesetzt, sie erfüllen die unten genannten Kriterien) für dieselbe Pseudo-Merge-Gruppe als Kandidaten betrachtet. Wenn das Muster stattdessen refs/remotes/([0-9])+/tags/ lautet, werden Tags von verschiedenen Remotes in separaten Pseudo-Merge-Gruppen basierend auf der Remote-Nummer gruppiert.

bitmapPseudoMerge.<name>.decay

Bestimmt die Rate, mit der aufeinanderfolgende Pseudo-Merge-Bitmap-Gruppen kleiner werden. Muss nicht-negativ sein. Dieser Parameter kann als k in der Funktion f(n) = C * n^-k betrachtet werden, wobei f(n) die Größe der `n`-ten Gruppe ist.

Wenn die Zerfallsrate auf 0 gesetzt wird, sind alle Gruppen gleich groß. Wenn die Zerfallsrate auf 1 gesetzt wird, ist die `n`-te Gruppe 1/n so groß wie die erste Gruppe. Höhere Zerfallswerte führen dazu, dass aufeinanderfolgende Gruppen mit zunehmender Rate schrumpfen. Der Standardwert ist 1.

Wenn alle Gruppen gleich groß sind, ist es möglich, dass Gruppen mit neueren Commits seltener verwendet werden können als frühere Gruppen, da es wahrscheinlicher ist, dass die Referenzen, die auf neuere Commits zeigen, häufiger aktualisiert werden als eine Referenz, die auf einen alten Commit zeigt.

bitmapPseudoMerge.<name>.sampleRate

Bestimmt den Anteil der nicht-bitmapmierten Commits (unter Referenzspitzen), die für die Aufnahme in eine instabile Pseudo-Merge-Bitmap ausgewählt werden. Muss zwischen 0 und 1 (einschließlich) liegen. Der Standardwert ist 1.

bitmapPseudoMerge.<name>.threshold

Bestimmt das Mindestalter von nicht-bitmapmierten Commits (unter Referenzspitzen, wie oben), die Kandidaten für die Aufnahme in eine instabile Pseudo-Merge-Bitmap sind. Der Standardwert ist 1.week.ago.

bitmapPseudoMerge.<name>.maxMerges

Bestimmt die maximale Anzahl von Pseudo-Merge-Commits, über die Commits verteilt werden können.

Für Pseudo-Merge-Gruppen, deren Muster keine Erfassungsgruppen enthält, wird diese Einstellung für alle mit dem regulären Ausdruck übereinstimmenden Commits angewendet. Für Muster mit einer oder mehreren Erfassungsgruppen wird diese Einstellung für jede einzelne Erfassungsgruppe angewendet.

Wenn Ihre Erfassungsgruppe beispielsweise refs/tags/ ist, werden alle Tags (außer wenn maxMerges explizit gesetzt wurde) in maximal maxMerges Pseudo-Merge-Commits verteilt. Wenn Ihre Erfassungsgruppe jedoch beispielsweise refs/remotes/([0-9]+)/tags/ lautet, wird diese Einstellung individuell für jeden Satz von Tags jedes Remotes angewendet.

Muss nicht-negativ sein. Der Standardwert ist 64.

bitmapPseudoMerge.<name>.stableThreshold

Bestimmt das Mindestalter von Commits (unter Referenzspitzen, wie oben; stabile Commits gelten jedoch auch dann als Kandidaten, wenn sie von einer Bitmap abgedeckt wurden), die Kandidaten für eine stabile Pseudo-Merge-Bitmap sind. Der Standardwert ist 1.month.ago.

Das Setzen dieses Schwellenwerts auf einen kleineren Wert (z.B. 1.week.ago) führt zur Generierung von mehr stabilen Gruppen (was einmalige Generierungskosten verursacht), aber diese Gruppen werden im Laufe der Zeit wahrscheinlich veralten. Die Verwendung eines größeren Wertes verursacht die entgegengesetzte Strafe (weniger stabile Gruppen, die nützlicher sind).

bitmapPseudoMerge.<name>.stableSize

Bestimmt die Größe (in Anzahl von Commits) einer stabilen Pseudo-Merge-Bitmap. Der Standardwert ist 512.

Beispiele

Angenommen, Sie haben ein Repository mit einer großen Anzahl von Referenzen und möchten eine abgespeckte Konfiguration von Pseudo-Merge-Bitmaps, die die Bitmap-Abdeckung des refs/-Namensraums verbessert. Sie können mit einer Konfiguration wie dieser beginnen:

[bitmapPseudoMerge "all"]
	pattern = "refs/"
	threshold = now
	stableThreshold = never
	sampleRate = 100
	maxMerges = 64

Dies erstellt Pseudo-Merge-Bitmaps für alle Referenzen, unabhängig von ihrem Alter, und gruppiert sie in 64 Pseudo-Merge-Commits.

Wenn Sie Tags von Branches bei der Generierung von Pseudo-Merge-Commits trennen möchten, würden Sie stattdessen das Muster mit einer Erfassungsgruppe definieren, wie folgt:

[bitmapPseudoMerge "all"]
	pattern = "refs/(heads/tags)/"

Angenommen stattdessen, Sie arbeiten in einem Fork-Netzwerk-Repository, wobei jeder Fork durch eine numerische ID identifiziert wird und seine Refs in refs/virtual/NNN/ liegen (wobei NNN die numerische ID ist, die einem bestimmten Fork entspricht). In diesem Fall könnten Sie stattdessen Folgendes schreiben:

[bitmapPseudoMerge "all"]
	pattern = "refs/virtual/([0-9]+)/(heads|tags)/"
	threshold = now
	stableThreshold = never
	sampleRate = 100
	maxMerges = 64

Dies würde Pseudo-Merge-Gruppen-Identifikatoren wie "1234-heads" und "5678-tags" (für Branches im Fork "1234" bzw. Tags im Remote "5678") generieren.

GIT

Teil der git[1] Suite