Mercurial > hg
changeset 31020:2d1bf84046f6
smartset: use native set operations as fast paths
For set operations like "&" and "-", where we know both basesets have their
sets ready, and the first set is sorted, use the native Python set
operations as a fast path.
Note: "+" is not optimized as that will break the ordering.
This leads to noticeable improvements on performance:
revset | before | after | delta
----------------------------------------------------------------
draft() & draft() & draft() & draft() | 776 | 477 | -39%
draft() + draft() + draft() + draft() | 2849 | 2864 |
draft() - draft() + draft() - draft() | 943 | 240 | -75%
draft() - draft() - draft() - draft() | 557 | 197 | -64%
(time measured in microseconds)
author | Jun Wu <quark@fb.com> |
---|---|
date | Sat, 18 Feb 2017 17:23:43 -0800 |
parents | 74f77f1c2215 |
children | 4189d790e8a4 |
files | mercurial/smartset.py |
diffstat | 1 files changed, 20 insertions(+), 4 deletions(-) [+] |
line wrap: on
line diff
--- a/mercurial/smartset.py Sat Feb 18 16:30:07 2017 -0800 +++ b/mercurial/smartset.py Sat Feb 18 17:23:43 2017 -0800 @@ -171,7 +171,7 @@ >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]] [[0, 4, 6, 7, 3, 5], [6, 7], [0, 4]] >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]] - ['addset', 'filteredset', 'filteredset'] + ['addset', 'baseset', 'baseset'] Construct by a list-like: >>> xs = baseset(x) @@ -191,18 +191,18 @@ >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]] ['addset', 'filteredset', 'filteredset'] - With sort(): + With sort(), set optimization could be used: >>> xs.sort(reverse=True) >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]] [[7, 6, 4, 0, 5, 3], [7, 6], [4, 0]] >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]] - ['addset', 'filteredset', 'filteredset'] + ['addset', 'baseset', 'baseset'] >>> ys.sort() >>> [list(i) for i in [xs + ys, xs & ys, xs - ys]] [[7, 6, 4, 0, 3, 5], [7, 6], [4, 0]] >>> [type(i).__name__ for i in [xs + ys, xs & ys, xs - ys]] - ['addset', 'filteredset', 'filteredset'] + ['addset', 'baseset', 'baseset'] """ def __init__(self, data=(), datarepr=None, istopo=False): """ @@ -322,6 +322,22 @@ return self._asclist[0] return None + def _fastsetop(self, other, op): + # try to use native set operations as fast paths + if (type(other) is baseset and '_set' in other.__dict__ and '_set' in + self.__dict__ and self._ascending is not None): + s = baseset(data=getattr(self._set, op)(other._set)) + s._ascending = self._ascending + else: + s = getattr(super(baseset, self), op)(other) + return s + + def __and__(self, other): + return self._fastsetop(other, '__and__') + + def __sub__(self, other): + return self._fastsetop(other, '__sub__') + def __repr__(self): d = {None: '', False: '-', True: '+'}[self._ascending] s = _formatsetrepr(self._datarepr)