libsolv/0005-Speed-up-choice-rule-generation.patch
2015-10-14 15:18:51 +02:00

134 lines
3.9 KiB
Diff

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