You are here -> Home Logram et son site » Nouveau solveur pour Setup

Nouveau solveur pour Setup

Le 19/05/2010 à 19h55 by steckdenis, in Logram et son site, 2 commentaries

Bonjour :) ,

Le solveur actuel de Setup, basé sur un algorithme intéressant à base de branches, fonctionne très bien dans l'immense majorité des cas, en étant très rapide.

Malheureusement, il souffre de deux problèmes :

  • Le code est difficilement maintenable, plein de petits hacks. Certains trucs marchent uniquement grâce à la chance, en particulier tout ce qui est gestion des branches. Il y a beaucoup de traces d'essais-erreurs, des hacks, etc.
  • Cette qualité de code, une des pires dans tout Setup (voire la pire depuis que j'ai refait l'installation des paquets) provoque de gros blocages. Dans certaines conditions, le solveur s'emballe et consomme toute la RAM disponible, sans trouver de solution. C'est inacceptable pour quelque-chose qui doit «juste marcher» chez les gens.

J'ai donc réfléchi à une amélioration de l'algorithme actuel, et ai trouvé l'algo le plus simple et le plus évident qu'on puisse imaginer. Il tient en moins de 1000 lignes (mais n'est pas encore complet, loin de là).

L'algo

En quelques mots : créer un arbre de dépendances. Simple. Il suffit de parcourir la base de donnée, d'ajouter les dépendances, retirer les conflits. La bonne métode bien naïve. Quand il y a des choix, c'est simple aussi, on les enregistre.

Par exemple, si A dépend de B qui dépend de C ou D, on a un arbre comme ceci :

  • A
    • B
      • choix :
        • C
        • D

Le tout est implémenté en presque pur C, avec très peu de Qt-ismes (tout de la gestion des pointeurs, quasiment pas de QList et QHash, c'est bien plus léger qu'avant).

Bon, maintenant qu'on a un arbre, il y a des détails à régler. Tout d'abord, il faut le peser. C'est expliqué dans mon journal, que je vous invite à lire.

Ensuite, pour ce qui est des dépendances en boucle, c'est géré tout seul par un side-effect. Pour les autres vérifications (pas installer un conflit, etc), c'est prévu mais pas encore fait.

Nouvelles fonctionnalités

Comme c'était assez facile d'avoir une base d'algo qui marche, j'en ai profité pour développer des trucs autours :

  • «setup -G add setup» génère le graphe (en utilisant graphviz) des dépendances de Setup qui doivent être installées.
  • «setup -G -nI add setup» fait la même chose mais avec les dépendances complètes, donc pas seulement ce qui sera installé. On a donc tout l'arbre, jusqu'à la LibC (alors qu'il s'arrête à Qt si Qt est déjà installé, normalement).
  • Le paramètre -nI ignore donc ce qui est déjà installé, ce qui permet de forcer une réinstallation de toutes les dépendances d'un paquet si la BDD est cassée.
  • Le paramètre -nD ignore les dépendances (comme pacman -Rd). Ainsi, si quelque-chose est cassé, on peut forcer la main à Setup. -nI -nD permet de forcer la réinstallation d'un paquet :) .

Et voilà le travail (le rond bleu représente un choix) :

Graphes Setup

Et si vous voulez voir ce que donne «setup -G -nI add setup», voici (Root est le noeud racine qui dépend de ce qu'on a demandé d'installer ;) ) : Fichiers PDF parce que le PNG est trop gros.

Le code est dans Gitorious, mais ne mettez pas à jour si vous utilisez vraiment Setup, l'installation ne marche pas, on ne sait que générer des graphes.

Commentaries

Author Message
steckdenis
# le 20/05/2010 à 19h25
Ça marche !
Avatar
Group : Administrateur

Bonjour,

Quelques de finitions aujourd'hui (j'ai viré des TODO) :

  • Gestion des dépendances des paquets venant directement des .lpk. Une bonne chose de faite. J'ai évité pas mal de duplication de code, là où l'ancien solveur en avait beaucoup.
  • Gestion des dépendances inverses. C'est très complet, aucune solution n'est oubliée, et super rapide

Côté rapidité, le graphe suivant est généré par Setup en 0.040 secondes (0.038 si on ne compte pas la génération du .dot), le tout sur un AMD Athlon L110 à 1,2Ghz, monocoeur, 512K de cache (c'est à dire encore moins qu'un Atom) : Image un peu grosse.

Le rose indique que ce sont des paquets qu'on supprime. Ils sont en noir si on les installe.

Maintenant, la vérification des noeuds, partie assez difficile car elle doit faire échouer des branches. Heureusement, c'est assez simple, il suffit d'ajouter une Solver::Node::Error à un noeud pour qu'il soit considéré comme mauvais.

KDE le fait depuis 10 ans.

steckdenis
# le 24/05/2010 à 15h15
Ça marche !
Avatar
Group : Administrateur

Bonjour,

J'ai finalement réussi à faire la partie difficile, c'est à dire la propagation des poids. Chaque paquet est en effet pesé individuellement. Il faut ensuite, pour chaque paquet, trouver son poids minimum et maximum en fonction des enfants qu'on lui choisi. C'est ce qui permet d'afficher les messages du genre «Installation de 34Mio à 56Mio».

Le code est sur Gitorious, les graphes générés sont tous beaux :) . En voici un par exemple, avec une version de less supplémentaire à laquelle j'ai rajouté des fichiers de débogage comme dépendance :

Dépendances pesées

Les légendes sont de la forme «min -> max», avec, dans l'ordre, le poids, la taille à télécharger, et la taille installée.

Je peux maintenant m'atteler à la partie du solveur qui va se charger de créer les listes. Elle va en fait se balader dans l'arbre, controlée par Setup (futur LPM à en croire le sondage), ou par le build server.

KDE le fait depuis 10 ans.