Comparaison DAG efficace sur un réseau

11

Dans les systèmes de contrôle de version distribués (tels que Mercurial et Git ), il est nécessaire de comparer efficacement les graphiques acycliques dirigés (DAG). Je suis un développeur Mercurial, et nous serions très intéressés d'entendre des travaux théoriques qui discutent de la complexité temporelle et réseau de la comparaison de deux DAG.

Les DAG en question sont constitués par les révisions enregistrées. Les révisions sont identifiées de manière unique par une valeur de hachage. Chaque révision dépend de zéro (validation initiale), une (validation normale) ou plusieurs (validation de fusion) des révisions précédentes. Voici un exemple où les révisions aà eont été faites l' une après l'autre:

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

La comparaison du graphique apparaît dans l'image lorsque quelqu'un n'a qu'une partie de l'historique et veut récupérer la partie manquante. Imaginez que je devais aà cet fait xet ybasé sur c:

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

Dans Mercurial, je ferais hg pullet téléchargerais det e:

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

Le but est d'identifier det eefficacement lorsque le graphe comporte de nombreux (disons, plus de 100 000) nœuds. L'efficacité concerne à la fois

  • complexité du réseau: le nombre d'octets transférés et le nombre d'aller-retour réseau nécessaires
  • complexité temporelle: quantité de calculs effectués par les deux serveurs qui échangent des changesets

Les graphiques typiques seront étroits avec quelques pistes parallèles comme ci-dessus. Il y aura également généralement seulement une poignée de nœuds foliaires (nous les appelons têtes dans Mercurial) comme eet yau - dessus. Enfin, lorsqu'un serveur central est utilisé, le client aura souvent quelques ensembles de modifications qui ne sont pas sur le serveur, tandis que le serveur peut avoir plus de 100 nouveaux ensembles de modifications pour les clients, en fonction de qui il y a longtemps, le client a été retiré du serveur pour la dernière fois. . Une solution asymétrique est privilégiée: un serveur centralisé devrait faire peu de calcul par rapport à ses clients.

Martin Geisler
la source
La discussion s'est un peu poursuivie sur Google Plus .
Martin Geisler

Réponses:

13

Dans ce contexte, les nœuds de graphe ont une sorte d'identifiant unique (un hachage ou une somme de contrôle), non? Vous n'avez donc pas besoin de faire de test d'isomorphisme sous-graphique, vous avez juste besoin d'une liste des nœuds qui diffèrent entre vos deux versions, et les bords ne sont pas vraiment utiles du tout pour cette étape. Mon article SIGCOMM 2011 " Quelle est la différence? Réconciliation efficace des ensembles sans contexte préalable"(avec Goodrich, Uyeda et Varghese) considère exactement ce problème: il s'avère que vous pouvez déterminer les identités des nœuds détenus par un mais pas les deux serveurs communicants, en utilisant une quantité de communication proportionnelle uniquement au nombre de nœuds modifiés et en n'utilisant qu'un seul aller-retour. Une fois que vous avez ces informations, il est facile de tirer les modifications elles-mêmes dans un deuxième aller-retour, là encore avec une communication optimale.

David Eppstein
la source
Euh, cela semble intéressant! Vous avez raison qu'une comparaison directe des ID d'ensemble de modifications (oui, ce sont des valeurs de hachage) fonctionnera. Nous essayons juste toujours d'utiliser la structure du graphe aussi: si nous connaissons tous les deux X, alors je sais aussi que vous connaissez tous les ancêtres de X. Cela semble être une information importante, mais peut-être pas. Je vais lire votre article maintenant, merci pour le pointeur!
Martin Geisler
@David: Une précision (je suis l'un des auteurs de l'algorithme actuellement utilisé par Mercurial). Nous nous soucions en fait de l'ensemble des nœuds "communs", pas besoin de connaître la valeur du nœud manquant.
tonfa
1
Si vous savez ce qui est différent, vous savez aussi ce qui est commun: c'est tout ce dont vous avez une copie qui ne fait pas la différence. Mais la différence doit généralement être relativement faible même lorsque la partie commune est grande, donc communiquer uniquement une quantité de données proportionnelle à la différence est préférable à la communication de l'ensemble du DAG historique ou de la partie commune.
David Eppstein
@David: en raison de la relation d'ancêtre, nous calculons en fait les têtes (nœuds foliaires) de la région commune. C'est donc encore une petite quantité de données, même s'il y a une énorme histoire partagée.
Martin Geisler
J'ai mis à jour ma réponse pour inclure également le nombre de voyages aller-retour utilisés (ce qui s'avère très faible).
David Eppstein
3

Dans la solution que nous avons implémentée pour Mercurial, une autre préoccupation était l'asymétrie: la charge du serveur devrait être minimisée à la fois pour la bande passante sortante et le temps CPU, au détriment de la charge du client.

Peter Arrenbrecht
la source
1
Merci, j'ai un peu mis à jour la question pour le noter.
Martin Geisler
0

Cela me semble être un processus en deux étapes.

  1. demander à tous les clients s'ils se sont engagés où le parent est c
  2. si oui, trouvez tous les enfants de c

La tâche de 1. Je pense qu'elle est principalement traitée côté client, et tout le client a besoin du hachage de validation sur le net.

Ron
la source
Quel scénario décrivez-vous? Le cas où j'ai fait xet yet dois tirer eet ddu serveur? Le problème initial est que je (en tant que client) ne connais pas le «point de branchement» c.
Martin Geisler