Вот быстрая замена RevisionSet, которая превращает его в набор. Это должно быть намного быстрее. Я не полностью протестировал это, но это работало со всеми тестами, которые я сделал. Несомненно, есть и другие способы ускорить процесс, но я думаю, что это действительно поможет, потому что он на самом деле использует быструю реализацию множеств, а не выполнение циклов в Python, которые исходный код выполнял в таких функциях, как __sub__
и __and__
. Единственная проблема в том, что итератор не отсортирован. Возможно, вам придется немного изменить код, чтобы учесть это. Я уверен, что есть и другие способы улучшить это, но, надеюсь, это даст вам хорошее начало.
class RevisionSet(set):
"""
A set of revisions, held in dictionary form for easy manipulation. If we
were to rewrite this script for Python 2.3+, we would subclass this from
set (or UserSet). As this class does not include branch
information, it's assumed that one instance will be used per
branch.
"""
def __init__(self, parm):
"""Constructs a RevisionSet from a string in property form, or from
a dictionary whose keys are the revisions. Raises ValueError if the
input string is invalid."""
revision_range_split_re = re.compile('[-:]')
if isinstance(parm, set):
print "1"
self.update(parm.copy())
elif isinstance(parm, list):
self.update(set(parm))
else:
parm = parm.strip()
if parm:
for R in parm.split(","):
rev_or_revs = re.split(revision_range_split_re, R)
if len(rev_or_revs) == 1:
self.add(int(rev_or_revs[0]))
elif len(rev_or_revs) == 2:
self.update(set(range(int(rev_or_revs[0]),
int(rev_or_revs[1])+1)))
else:
raise ValueError, 'Ill formatted revision range: ' + R
def sorted(self):
return sorted(self)
def normalized(self):
"""Returns a normalized version of the revision set, which is an
ordered list of couples (start,end), with the minimum number of
intervals."""
revnums = sorted(self)
revnums.reverse()
ret = []
while revnums:
s = e = revnums.pop()
while revnums and revnums[-1] in (e, e+1):
e = revnums.pop()
ret.append((s, e))
return ret
def __str__(self):
"""Convert the revision set to a string, using its normalized form."""
L = []
for s,e in self.normalized():
if s == e:
L.append(str(s))
else:
L.append(str(s) + "-" + str(e))
return ",".join(L)
Дополнительно:
Между прочим, я сравнил выполнение объединений, пересечений и вычитаний исходного RevisionSet и моего RevisionSet выше, и приведенный выше код в 3–7 раз быстрее для этих операций при работе с двумя RevisionSet, которые имеют 75000 элементов. Я знаю, что другие люди говорят, что NumPy - это путь, но если вы не очень разбираетесь в Python, как указывает ваш комментарий, то вы, возможно, не захотите идти по этому пути, потому что это повлечет за собой гораздо больше изменений. Я бы порекомендовал попробовать мой код, посмотреть, работает ли он, и если да, то посмотреть, достаточно ли он быстр для вас. Если это не так, то я бы попробовал профилирование, чтобы увидеть, что нужно улучшить. Только тогда я мог бы рассмотреть возможность использования numpy (это отличный пакет, который я использую довольно часто).