From 843952d627b9a1a12ef08c923bc6b4612f8134fe Mon Sep 17 00:00:00 2001 From: Niels Thykier Date: Sun, 31 May 2015 22:26:16 +0200 Subject: [PATCH] Avoid O(n^2) duplication handling when building hints Use a set to filter out seen items to avoid doing O(n^2) de-duplication. For very large hints, this can take considerable time. Using "seen_items" to build the actual hints on the (unverified) assumption that Python can do something "smart" to turn a set into a frozenset faster than it can with a list. Signed-off-by: Niels Thykier --- britney.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/britney.py b/britney.py index 9ad4333..d36a19b 100755 --- a/britney.py +++ b/britney.py @@ -2862,23 +2862,29 @@ class Britney(object): candidates.append(h) seen_hints.add(h) else: - items = [ (e, excuse.ver[1]) ] + items = [(e, excuse.ver[1])] orig_size = 1 looped = False + seen_items = set() + seen_items.update(items) + for item, ver in items: # excuses which depend on "item" or are depended on by it - items.extend( (x, excuses[x].ver[1]) for x in excuses if \ + new_items = [(x, excuses[x].ver[1]) for x in excuses if \ (item in excuses[x].deps or x in excuses[item].deps) \ - and (x, excuses[x].ver[1]) not in items ) + and (x, excuses[x].ver[1]) not in seen_items] + items.extend(new_items) + seen_items.update(new_items) + if not looped and len(items) > 1: orig_size = len(items) - h = frozenset(items) + h = frozenset(seen_items) if h not in seen_hints: mincands.append(h) seen_hints.add(h) looped = True if len(items) != orig_size: - h = frozenset(items) + h = frozenset(seen_items) if h != mincands[-1] and h not in seen_hints: candidates.append(h) seen_hints.add(h)