Effizienter DAG-Vergleich über ein Netzwerk


11

In verteilten Versionskontrollsystemen (wie Mercurial und Git ) müssen gerichtete azyklische Graphen (DAGs) effizient verglichen werden. Ich bin ein Mercurial-Entwickler, und wir wären sehr daran interessiert, etwas über theoretische Arbeiten zu erfahren, in denen die Zeit- und Netzwerkkomplexität des Vergleichs zweier DAGs erörtert wird.

Die fraglichen DAGs werden durch die aufgezeichneten Revisionen gebildet. Revisionen werden durch einen Hashwert eindeutig identifiziert. Jede Revision hängt von null (anfängliches Commit), einem (normales Commit) oder mehreren (Merge Commit) der vorherigen Revisionen ab. Hier ist ein Beispiel , wo Revisionen azu egemacht wurden einer nach dem sie:

a --- b --- c --- d --- e

Der Diagrammvergleich wird angezeigt, wenn jemand nur einen Teil des Verlaufs hat und den fehlenden Teil abrufen möchte. Stellen Sie sich vor ich hatte azu cund machte xund auf yBasis von c:

a --- b --- c --- x --- y

In Mercurial würde ich tun hg pullund herunterladen dund e:

a --- b --- c --- x --- y
              \
                d --- e

Das Ziel besteht darin, zu identifizieren dund eeffizient zu sein, wenn der Graph viele (beispielsweise mehr als 100.000) Knoten hat. Effizienz betrifft beides

  • Netzwerkkomplexität: Die Anzahl der übertragenen Bytes und die Anzahl der erforderlichen Netzwerk-Roundtrips
  • Zeitkomplexität: Der Rechenaufwand der beiden Server, die Änderungssätze austauschen

Typische Diagramme sind schmal mit wenigen parallelen Spuren wie oben. Es wird normalerweise auch nur eine Handvoll Blattknoten (wir nennen sie in Mercurial Köpfe) wie eund ydarüber geben. Wenn ein zentraler Server verwendet wird, verfügt der Client häufig über einige Änderungssätze, die sich nicht auf dem Server befinden, während der Server über 100 neue Änderungssätze für die Clients verfügen kann, je nachdem, wer den Client vor langer Zeit zuletzt vom Server abgerufen hat . Eine asymmetrische Lösung wird bevorzugt: Ein zentraler Server sollte im Vergleich zu seinen Clients nur wenig rechnen.


Die Diskussion über Google Plus wurde ein wenig fortgesetzt .
Martin Geisler

Antworten:


13

In diesem Zusammenhang haben die Diagrammknoten eine eindeutige Kennung (einen Hash oder eine Prüfsumme), oder? Sie müssen also keine Subgraph-Isomorphismustests durchführen. Sie benötigen lediglich eine Liste der Knoten, die sich zwischen Ihren beiden Versionen unterscheiden, und die Kanten sind für diesen Schritt überhaupt nicht nützlich. Mein SIGCOMM 2011-Artikel " Was ist der Unterschied? Effiziente Set-Abstimmung ohne vorherigen Kontext"(mit Goodrich, Uyeda und Varghese) betrachtet genau dieses Problem: Es stellt sich heraus, dass Sie die Identität der Knoten, die von einem, aber nicht von beiden Kommunikationsservern gehalten werden, mithilfe einer nur proportionalen Kommunikationsmenge bestimmen können auf die Anzahl der geänderten Knoten und mit nur einem einzigen Roundtrip. Sobald Sie diese Informationen haben, ist es einfach, die Änderungen in einem zweiten Roundtrip selbst mit optimaler Kommunikation abzurufen.


Äh, das klingt interessant! Sie haben Recht, dass ein direkter Vergleich der Änderungssatz-IDs (ja, es handelt sich um Hash-Werte) funktioniert. Wir haben nur immer versucht, auch die Diagrammstruktur zu verwenden: Wenn wir beide X kennen, weiß ich auch, dass Sie alle Vorfahren von X kennen. Das scheint eine wichtige Information zu sein, ist es aber vielleicht nicht. Ich werde jetzt Ihre Zeitung lesen, danke für den Hinweis!
Martin Geisler

@ David: Eine Präzision (ich bin einer der Autoren des derzeit von Mercurial verwendeten Algorithmus). Wir kümmern uns tatsächlich um die Menge der "gemeinsamen" Knoten, ohne den Wert des fehlenden Knotens kennen zu müssen.
Tonfa

1
Wenn Sie wissen, was anders ist, dann wissen Sie auch, was gemeinsam ist: Es ist alles, von dem Sie eine Kopie haben, nicht Teil des Unterschieds. Der Unterschied sollte jedoch in der Regel relativ gering sein, selbst wenn der gemeinsame Teil groß ist. Daher ist es besser, nur eine Datenmenge zu kommunizieren, die proportional zum Unterschied ist, als die gesamte Verlaufs-DAG oder den gemeinsamen Teil zu kommunizieren.
David Eppstein

@ David: Aufgrund der Ahnenbeziehung berechnen wir tatsächlich die Köpfe (Blattknoten) der gemeinsamen Region. Das ist also immer noch eine kleine Datenmenge, selbst wenn es eine große gemeinsame Geschichte gibt.
Martin Geisler

Ich habe meine Antwort aktualisiert und auch die Anzahl der verwendeten Hin- und Rückfahrten angegeben (was sich als sehr gering herausstellt).
David Eppstein

3

Bei der für Mercurial implementierten Lösung war ein weiteres Problem die Asymmetrie: Die Auslastung des Servers sollte sowohl für die ausgehende Bandbreite als auch für die CPU-Zeit auf Kosten der Auslastung des Clients minimiert werden.


1
Danke, ich habe die Frage ein wenig aktualisiert, um dies zu beachten.
Martin Geisler

0

Klingt für mich nach einem zweistufigen Prozess.

  1. Fragen Sie alle Kunden, ob sie Commits haben, bei denen sich der Elternteil befindet. c
  2. Wenn ja, finden Sie alle Kinder von c

Die Aufgabe von 1. Ich denke, wird hauptsächlich auf der Client-Seite verarbeitet, und alle Clients benötigen den Commit-Hash über das Netz.


Welches Szenario beschreiben Sie? Der Fall, wo ich gemacht habe xund yund muss eund dvom Server ziehen? Das anfängliche Problem dort ist, dass ich (als Kunde) den "Verzweigungspunkt" nicht kenne c.
Martin Geisler
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.