Blob Blame History Raw
From ac0801c908fb25c8d9d1384470c26d6ffc991c3d Mon Sep 17 00:00:00 2001
From: Michael Schroeder <mls@suse.de>
Date: Wed, 14 Oct 2015 11:12:53 +0200
Subject: [PATCH 5/6] Speed up choice rule generation

Reduce the amount of package filtering calls. Brings down the choice
rule creation time from 18ms to 8ms on my system.
---
 src/rules.c | 68 ++++++++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 45 insertions(+), 23 deletions(-)

diff --git a/src/rules.c b/src/rules.c
index cb45098..97ccc6e 100644
--- a/src/rules.c
+++ b/src/rules.c
@@ -2833,32 +2833,51 @@ solver_rule2rules(Solver *solv, Id rid, Queue *q, int recursive)
 
 /* check if the newest versions of pi still provides the dependency we're looking for */
 static int
-solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m)
+solver_choicerulecheck(Solver *solv, Id pi, Rule *r, Map *m, Queue *q)
 {
   Pool *pool = solv->pool;
   Rule *ur;
-  Queue q;
-  Id p, pp, qbuf[32];
+  Id p, pp;
   int i;
 
-  ur = solv->rules + solv->updaterules + (pi - pool->installed->start);
-  if (!ur->p)
-    ur = solv->rules + solv->featurerules + (pi - pool->installed->start);
-  if (!ur->p)
-    return 0;
-  queue_init_buffer(&q, qbuf, sizeof(qbuf)/sizeof(*qbuf));
-  FOR_RULELITERALS(p, pp, ur)
-    if (p > 0)
-      queue_push(&q, p);
-  if (q.count > 1)
-    policy_filter_unwanted(solv, &q, POLICY_MODE_CHOOSE);
-  for (i = 0; i < q.count; i++)
-    if (MAPTST(m, q.elements[i]))
-      break;
-  /* 1: none of the newest versions provide it */
-  i = i == q.count ? 1 : 0;
-  queue_free(&q);
-  return i;
+  if (!q->count || q->elements[0] != pi)
+    {
+      if (q->count)
+        queue_empty(q);
+      ur = solv->rules + solv->updaterules + (pi - pool->installed->start);
+      if (!ur->p)
+        ur = solv->rules + solv->featurerules + (pi - pool->installed->start);
+      if (!ur->p)
+	return 0;
+      queue_push2(q, pi, 0);
+      FOR_RULELITERALS(p, pp, ur)
+	if (p > 0)
+	  queue_push(q, p);
+    }
+  if (q->count == 2)
+    return 1;
+  if (q->count == 3)
+    {
+      p = q->elements[2];
+      return MAPTST(m, p) ? 0 : 1;
+    }
+  if (!q->elements[1])
+    {
+      for (i = 2; i < q->count; i++)
+	if (!MAPTST(m, q->elements[i]))
+	  break;
+      if (i == q->count)
+	return 0;	/* all provide it, no need to filter */
+      /* some don't provide it, have to filter */
+      queue_deleten(q, 0, 2);
+      policy_filter_unwanted(solv, q, POLICY_MODE_CHOOSE);
+      queue_unshift(q, 1);	/* filter mark */
+      queue_unshift(q, pi);
+    }
+  for (i = 2; i < q->count; i++)
+    if (MAPTST(m, q->elements[i]))
+      return 0;		/* at least one provides it */
+  return 1;	/* none of the new packages provided it */
 }
 
 static inline void
@@ -2883,7 +2902,7 @@ solver_addchoicerules(Solver *solv)
   Pool *pool = solv->pool;
   Map m, mneg;
   Rule *r;
-  Queue q, qi;
+  Queue q, qi, qcheck;
   int i, j, rid, havechoice;
   Id p, d, pp;
   Id p2, pp2;
@@ -2902,6 +2921,7 @@ solver_addchoicerules(Solver *solv)
   solv->choicerules_ref = solv_calloc(solv->pkgrules_end, sizeof(Id));
   queue_init(&q);
   queue_init(&qi);
+  queue_init(&qcheck);
   map_init(&m, pool->nsolvables);
   map_init(&mneg, pool->nsolvables);
   /* set up negative assertion map from infarch and dup rules */
@@ -3019,7 +3039,7 @@ solver_addchoicerules(Solver *solv)
 	  p2 = qi.elements[i];
 	  if (!p2)
 	    continue;
-	  if (solver_choicerulecheck(solv, p2, r, &m))
+	  if (solver_choicerulecheck(solv, p2, r, &m, &qcheck))
 	    {
 	      /* oops, remove element p from q */
 	      queue_removeelement(&q, qi.elements[i + 1]);
@@ -3028,6 +3048,7 @@ solver_addchoicerules(Solver *solv)
 	  qi.elements[j++] = p2;
 	}
       queue_truncate(&qi, j);
+
       if (!q.count || !qi.count)
 	{
 	  FOR_RULELITERALS(p, pp, r)
@@ -3099,6 +3120,7 @@ solver_addchoicerules(Solver *solv)
     }
   queue_free(&q);
   queue_free(&qi);
+  queue_free(&qcheck);
   map_free(&m);
   map_free(&mneg);
   solv->choicerules_end = solv->nrules;
-- 
2.4.3