[PATCH 2 of 2 V2] smartset: use native set operations as fast paths
Jun Wu
quark at fb.com
Sun Feb 19 01:27:31 UTC 2017
# HG changeset patch
# User Jun Wu <quark at fb.com>
# Date 1487467423 28800
# Sat Feb 18 17:23:43 2017 -0800
# Node ID 6f57ef05c74567db95f42426499640ad29bc878f
# Parent deb48622b857d621606a1cdda4adc868b1c663d4
# Available At https://bitbucket.org/quark-zju/hg-draft
# hg pull https://bitbucket.org/quark-zju/hg-draft -r 6f57ef05c745
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)
diff --git a/mercurial/smartset.py b/mercurial/smartset.py
--- a/mercurial/smartset.py
+++ b/mercurial/smartset.py
@@ -172,5 +172,5 @@ class baseset(abstractsmartset):
[[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:
@@ -192,10 +192,10 @@ class baseset(abstractsmartset):
['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()
@@ -203,5 +203,5 @@ class baseset(abstractsmartset):
[[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):
@@ -323,4 +323,20 @@ class baseset(abstractsmartset):
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]
More information about the Mercurial-devel
mailing list