Patchwork [4,of,4] revset: added intersection to baseset class

login
register
mail settings
Submitter Lucas Moscovicz
Date Feb. 3, 2014, 7:44 p.m.
Message ID <c7a2e2891d64dc826a30.1391456675@dev1037.prn2.facebook.com>
Download mbox | patch
Permalink /patch/3440/
State Accepted
Commit 2ac278aab2b48f9cba1e282ff722b5bef73507af
Headers show

Comments

Lucas Moscovicz - Feb. 3, 2014, 7:44 p.m.
# HG changeset patch
# User Lucas Moscovicz <lmoscovicz@fb.com>
# Date 1390611464 28800
#      Fri Jan 24 16:57:44 2014 -0800
# Node ID c7a2e2891d64dc826a305983e14b678cb922f97b
# Parent  f6b40a0e62bbdcfc8aaa10f0b678428809a8c729
revset: added intersection to baseset class

Added the method __and__ to the baseset class to be able to intersect with
other objects in a more efficient way.
Lucas Moscovicz - Feb. 3, 2014, 11:44 p.m.
This are the time benchmarks for the 4 patches compared with the original
code.
Times haven¹t improved a lot but this will be useful for further patches.

Revsets to benchmark
----------------------------
0) draft()
1) draft() and ::tip
2) roots(0::tip)
3) author(lmoscovicz)
4) author(lmoscovicz) or author(mpm)
----------------------------

Benchmarking baseline
0) ! wall 0.022047 comb 0.020000 user 0.020000 sys 0.000000 (best of 135)
1) ! wall 0.079870 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)
2) ! wall 0.129004 comb 0.130000 user 0.130000 sys 0.000000 (best of 76)
3) ! wall 1.932607 comb 1.930000 user 1.920000 sys 0.010000 (best of 6)
4) ! wall 3.922935 comb 3.920000 user 3.910000 sys 0.010000 (best of 3)


----------------------------
revset: added baseset class (still empty) to improve revset performance
----------------------------
0) ! wall 0.022075 comb 0.020000 user 0.020000 sys 0.000000 (best of 134)
1) ! wall 0.080349 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)
2) ! wall 5.999530 comb 5.990000 user 5.990000 sys 0.000000 (best of 3)
3) ! wall 1.956068 comb 1.950000 user 1.950000 sys 0.000000 (best of 6)
4) ! wall 3.929954 comb 3.930000 user 3.920000 sys 0.010000 (best of 3)
----------------------------

----------------------------
revset: implemented set caching for revset evaluation
----------------------------
0) ! wall 0.021979 comb 0.030000 user 0.030000 sys 0.000000 (best of 134)
1) ! wall 0.080377 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)
2) ! wall 6.021458 comb 6.010000 user 6.010000 sys 0.000000 (best of 3)
3) ! wall 1.935738 comb 1.940000 user 1.930000 sys 0.010000 (best of 6)
4) ! wall 3.938362 comb 3.930000 user 3.920000 sys 0.010000 (best of 3)
----------------------------

----------------------------
revset: added substraction to baseset class
----------------------------
0) ! wall 0.022804 comb 0.020000 user 0.020000 sys 0.000000 (best of 130)
1) ! wall 0.082532 comb 0.090000 user 0.090000 sys 0.000000 (best of 100)
2) ! wall 0.132322 comb 0.130000 user 0.130000 sys 0.000000 (best of 74)
3) ! wall 1.977425 comb 1.970000 user 1.970000 sys 0.000000 (best of 6)
4) ! wall 3.893846 comb 3.890000 user 3.890000 sys 0.000000 (best of 3)
----------------------------

----------------------------
revset: added intersection to baseset class
----------------------------
0) ! wall 0.022130 comb 0.020000 user 0.020000 sys 0.000000 (best of 134)
1) ! wall 0.079776 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)
2) ! wall 0.131943 comb 0.130000 user 0.130000 sys 0.000000 (best of 74)
3) ! wall 1.954395 comb 1.950000 user 1.950000 sys 0.000000 (best of 6)
4) ! wall 3.888849 comb 3.890000 user 3.880000 sys 0.010000 (best of 3)



On 2/3/14, 11:44 AM, "Lucas Moscovicz" <lmoscovicz@fb.com> wrote:

># HG changeset patch
># User Lucas Moscovicz <lmoscovicz@fb.com>
># Date 1390611464 28800
>#      Fri Jan 24 16:57:44 2014 -0800
># Node ID c7a2e2891d64dc826a305983e14b678cb922f97b
># Parent  f6b40a0e62bbdcfc8aaa10f0b678428809a8c729
>revset: added intersection to baseset class
>
>Added the method __and__ to the baseset class to be able to intersect with
>other objects in a more efficient way.
>
>diff --git a/mercurial/revset.py b/mercurial/revset.py
>--- a/mercurial/revset.py
>+++ b/mercurial/revset.py
>@@ -402,8 +402,7 @@
>             bmrevs = set()
>             for bmrev in matchrevs:
>                 bmrevs.add(repo[bmrev].rev())
>-            s = subset.set()
>-            return baseset([r for r in s if r in bmrevs])
>+            return subset & bmrevs
> 
>     bms = set([repo[r].rev()
>                for r in repo._bookmarks.values()])
>@@ -450,7 +449,7 @@
>     # i18n: "bumped" is a keyword
>     getargs(x, 0, 0, _("bumped takes no arguments"))
>     bumped = obsmod.getrevs(repo, 'bumped')
>-    return baseset([r for r in subset if r in bumped])
>+    return subset & bumped
> 
> def bundle(repo, subset, x):
>     """``bundle()``
>@@ -462,7 +461,7 @@
>         bundlerevs = repo.changelog.bundlerevs
>     except AttributeError:
>         raise util.Abort(_("no bundle provided - specify with -R"))
>-    return baseset([r for r in subset if r in bundlerevs])
>+    return subset & bundlerevs
> 
> def checkstatus(repo, subset, pat, field):
>     m = None
>@@ -515,7 +514,7 @@
>     """
>     s = getset(repo, baseset(repo), x).set()
>     cs = _children(repo, subset, s)
>-    return baseset([r for r in subset if r in cs])
>+    return subset & cs
> 
> def closed(repo, subset, x):
>     """``closed()``
>@@ -680,7 +679,7 @@
>     # i18n: "extinct" is a keyword
>     getargs(x, 0, 0, _("extinct takes no arguments"))
>     extincts = obsmod.getrevs(repo, 'extinct')
>-    return baseset([r for r in subset if r in extincts])
>+    return subset & extincts
> 
> def extra(repo, subset, x):
>     """``extra(label, [value])``
>@@ -906,7 +905,7 @@
>     # i18n: "hidden" is a keyword
>     getargs(x, 0, 0, _("hidden takes no arguments"))
>     hiddenrevs = repoview.filterrevs(repo, 'visible')
>-    return baseset([r for r in subset if r in hiddenrevs])
>+    return subset & hiddenrevs
> 
> def keyword(repo, subset, x):
>     """``keyword(string)``
>@@ -1039,7 +1038,7 @@
>     # i18n: "obsolete" is a keyword
>     getargs(x, 0, 0, _("obsolete takes no arguments"))
>     obsoletes = obsmod.getrevs(repo, 'obsolete')
>-    return baseset([r for r in subset if r in obsoletes])
>+    return subset & obsoletes
> 
> def origin(repo, subset, x):
>     """``origin([set])``
>@@ -1106,8 +1105,7 @@
>     cl = repo.changelog
>     for r in getset(repo, baseset(repo), x):
>         ps.add(cl.parentrevs(r)[0])
>-    s = subset.set()
>-    return baseset([r for r in s if r in ps])
>+    return subset & ps
> 
> def p2(repo, subset, x):
>     """``p2([set])``
>@@ -1125,8 +1123,7 @@
>     cl = repo.changelog
>     for r in getset(repo, baseset(repo), x):
>         ps.add(cl.parentrevs(r)[1])
>-    s = subset.set()
>-    return baseset([r for r in s if r in ps])
>+    return subset & ps
> 
> def parents(repo, subset, x):
>     """``parents([set])``
>@@ -1134,14 +1131,13 @@
>     """
>     if x is None:
>         ps = tuple(p.rev() for p in repo[x].parents())
>-        return baseset([r for r in subset if r in ps])
>+        return subset & ps
> 
>     ps = set()
>     cl = repo.changelog
>     for r in getset(repo, baseset(repo), x):
>         ps.update(cl.parentrevs(r))
>-    s = subset.set()
>-    return baseset([r for r in s if r in ps])
>+    return subset & ps
> 
> def parentspec(repo, subset, x, n):
>     """``set^0``
>@@ -1166,8 +1162,7 @@
>             parents = cl.parentrevs(r)
>             if len(parents) > 1:
>                 ps.add(parents[1])
>-    s = subset.set()
>-    return baseset([r for r in s if r in ps])
>+    return subset & ps
> 
> def present(repo, subset, x):
>     """``present(set)``
>@@ -1508,7 +1503,7 @@
>             s = set([cl.rev(n) for t, n in repo.tagslist() if
>matcher(t)])
>     else:
>         s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
>-    return baseset([r for r in subset if r in s])
>+    return subset & s
> 
> def tagged(repo, subset, x):
>     return tag(repo, subset, x)
>@@ -1520,7 +1515,7 @@
>     # i18n: "unstable" is a keyword
>     getargs(x, 0, 0, _("unstable takes no arguments"))
>     unstables = obsmod.getrevs(repo, 'unstable')
>-    return baseset([r for r in subset if r in unstables])
>+    return subset & unstables
> 
> 
> def user(repo, subset, x):
>@@ -2051,5 +2046,11 @@
>             s = set(x)
>         return baseset(self.set() - s)
> 
>+    def __and__(self, x):
>+        s = self.set()
>+        if isinstance(x, baseset):
>+            x = x.set()
>+        return baseset([y for y in s if y in x])
>+
> # tell hggettext to extract docstrings from these functions:
> i18nfunctions = symbols.values()
Lucas Moscovicz - Feb. 3, 2014, 11:48 p.m.
(Testing on hg repo)

On 2/3/14, 3:44 PM, "Lucas Moscovicz" <lmoscovicz@fb.com> wrote:

>This are the time benchmarks for the 4 patches compared with the original

>code.

>Times haven¹t improved a lot but this will be useful for further patches.

>

>Revsets to benchmark

>----------------------------

>0) draft()

>1) draft() and ::tip

>2) roots(0::tip)

>3) author(lmoscovicz)

>4) author(lmoscovicz) or author(mpm)

>----------------------------

>

>Benchmarking baseline

>0) ! wall 0.022047 comb 0.020000 user 0.020000 sys 0.000000 (best of 135)

>1) ! wall 0.079870 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)

>2) ! wall 0.129004 comb 0.130000 user 0.130000 sys 0.000000 (best of 76)

>3) ! wall 1.932607 comb 1.930000 user 1.920000 sys 0.010000 (best of 6)

>4) ! wall 3.922935 comb 3.920000 user 3.910000 sys 0.010000 (best of 3)

>

>

>----------------------------

>revset: added baseset class (still empty) to improve revset performance

>----------------------------

>0) ! wall 0.022075 comb 0.020000 user 0.020000 sys 0.000000 (best of 134)

>1) ! wall 0.080349 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)

>2) ! wall 5.999530 comb 5.990000 user 5.990000 sys 0.000000 (best of 3)

>3) ! wall 1.956068 comb 1.950000 user 1.950000 sys 0.000000 (best of 6)

>4) ! wall 3.929954 comb 3.930000 user 3.920000 sys 0.010000 (best of 3)

>----------------------------

>

>----------------------------

>revset: implemented set caching for revset evaluation

>----------------------------

>0) ! wall 0.021979 comb 0.030000 user 0.030000 sys 0.000000 (best of 134)

>1) ! wall 0.080377 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)

>2) ! wall 6.021458 comb 6.010000 user 6.010000 sys 0.000000 (best of 3)

>3) ! wall 1.935738 comb 1.940000 user 1.930000 sys 0.010000 (best of 6)

>4) ! wall 3.938362 comb 3.930000 user 3.920000 sys 0.010000 (best of 3)

>----------------------------

>

>----------------------------

>revset: added substraction to baseset class

>----------------------------

>0) ! wall 0.022804 comb 0.020000 user 0.020000 sys 0.000000 (best of 130)

>1) ! wall 0.082532 comb 0.090000 user 0.090000 sys 0.000000 (best of 100)

>2) ! wall 0.132322 comb 0.130000 user 0.130000 sys 0.000000 (best of 74)

>3) ! wall 1.977425 comb 1.970000 user 1.970000 sys 0.000000 (best of 6)

>4) ! wall 3.893846 comb 3.890000 user 3.890000 sys 0.000000 (best of 3)

>----------------------------

>

>----------------------------

>revset: added intersection to baseset class

>----------------------------

>0) ! wall 0.022130 comb 0.020000 user 0.020000 sys 0.000000 (best of 134)

>1) ! wall 0.079776 comb 0.080000 user 0.080000 sys 0.000000 (best of 100)

>2) ! wall 0.131943 comb 0.130000 user 0.130000 sys 0.000000 (best of 74)

>3) ! wall 1.954395 comb 1.950000 user 1.950000 sys 0.000000 (best of 6)

>4) ! wall 3.888849 comb 3.890000 user 3.880000 sys 0.010000 (best of 3)

>

>

>

>On 2/3/14, 11:44 AM, "Lucas Moscovicz" <lmoscovicz@fb.com> wrote:

>

>># HG changeset patch

>># User Lucas Moscovicz <lmoscovicz@fb.com>

>># Date 1390611464 28800

>>#      Fri Jan 24 16:57:44 2014 -0800

>># Node ID c7a2e2891d64dc826a305983e14b678cb922f97b

>># Parent  f6b40a0e62bbdcfc8aaa10f0b678428809a8c729

>>revset: added intersection to baseset class

>>

>>Added the method __and__ to the baseset class to be able to intersect

>>with

>>other objects in a more efficient way.

>>

>>diff --git a/mercurial/revset.py b/mercurial/revset.py

>>--- a/mercurial/revset.py

>>+++ b/mercurial/revset.py

>>@@ -402,8 +402,7 @@

>>             bmrevs = set()

>>             for bmrev in matchrevs:

>>                 bmrevs.add(repo[bmrev].rev())

>>-            s = subset.set()

>>-            return baseset([r for r in s if r in bmrevs])

>>+            return subset & bmrevs

>> 

>>     bms = set([repo[r].rev()

>>                for r in repo._bookmarks.values()])

>>@@ -450,7 +449,7 @@

>>     # i18n: "bumped" is a keyword

>>     getargs(x, 0, 0, _("bumped takes no arguments"))

>>     bumped = obsmod.getrevs(repo, 'bumped')

>>-    return baseset([r for r in subset if r in bumped])

>>+    return subset & bumped

>> 

>> def bundle(repo, subset, x):

>>     """``bundle()``

>>@@ -462,7 +461,7 @@

>>         bundlerevs = repo.changelog.bundlerevs

>>     except AttributeError:

>>         raise util.Abort(_("no bundle provided - specify with -R"))

>>-    return baseset([r for r in subset if r in bundlerevs])

>>+    return subset & bundlerevs

>> 

>> def checkstatus(repo, subset, pat, field):

>>     m = None

>>@@ -515,7 +514,7 @@

>>     """

>>     s = getset(repo, baseset(repo), x).set()

>>     cs = _children(repo, subset, s)

>>-    return baseset([r for r in subset if r in cs])

>>+    return subset & cs

>> 

>> def closed(repo, subset, x):

>>     """``closed()``

>>@@ -680,7 +679,7 @@

>>     # i18n: "extinct" is a keyword

>>     getargs(x, 0, 0, _("extinct takes no arguments"))

>>     extincts = obsmod.getrevs(repo, 'extinct')

>>-    return baseset([r for r in subset if r in extincts])

>>+    return subset & extincts

>> 

>> def extra(repo, subset, x):

>>     """``extra(label, [value])``

>>@@ -906,7 +905,7 @@

>>     # i18n: "hidden" is a keyword

>>     getargs(x, 0, 0, _("hidden takes no arguments"))

>>     hiddenrevs = repoview.filterrevs(repo, 'visible')

>>-    return baseset([r for r in subset if r in hiddenrevs])

>>+    return subset & hiddenrevs

>> 

>> def keyword(repo, subset, x):

>>     """``keyword(string)``

>>@@ -1039,7 +1038,7 @@

>>     # i18n: "obsolete" is a keyword

>>     getargs(x, 0, 0, _("obsolete takes no arguments"))

>>     obsoletes = obsmod.getrevs(repo, 'obsolete')

>>-    return baseset([r for r in subset if r in obsoletes])

>>+    return subset & obsoletes

>> 

>> def origin(repo, subset, x):

>>     """``origin([set])``

>>@@ -1106,8 +1105,7 @@

>>     cl = repo.changelog

>>     for r in getset(repo, baseset(repo), x):

>>         ps.add(cl.parentrevs(r)[0])

>>-    s = subset.set()

>>-    return baseset([r for r in s if r in ps])

>>+    return subset & ps

>> 

>> def p2(repo, subset, x):

>>     """``p2([set])``

>>@@ -1125,8 +1123,7 @@

>>     cl = repo.changelog

>>     for r in getset(repo, baseset(repo), x):

>>         ps.add(cl.parentrevs(r)[1])

>>-    s = subset.set()

>>-    return baseset([r for r in s if r in ps])

>>+    return subset & ps

>> 

>> def parents(repo, subset, x):

>>     """``parents([set])``

>>@@ -1134,14 +1131,13 @@

>>     """

>>     if x is None:

>>         ps = tuple(p.rev() for p in repo[x].parents())

>>-        return baseset([r for r in subset if r in ps])

>>+        return subset & ps

>> 

>>     ps = set()

>>     cl = repo.changelog

>>     for r in getset(repo, baseset(repo), x):

>>         ps.update(cl.parentrevs(r))

>>-    s = subset.set()

>>-    return baseset([r for r in s if r in ps])

>>+    return subset & ps

>> 

>> def parentspec(repo, subset, x, n):

>>     """``set^0``

>>@@ -1166,8 +1162,7 @@

>>             parents = cl.parentrevs(r)

>>             if len(parents) > 1:

>>                 ps.add(parents[1])

>>-    s = subset.set()

>>-    return baseset([r for r in s if r in ps])

>>+    return subset & ps

>> 

>> def present(repo, subset, x):

>>     """``present(set)``

>>@@ -1508,7 +1503,7 @@

>>             s = set([cl.rev(n) for t, n in repo.tagslist() if

>>matcher(t)])

>>     else:

>>         s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])

>>-    return baseset([r for r in subset if r in s])

>>+    return subset & s

>> 

>> def tagged(repo, subset, x):

>>     return tag(repo, subset, x)

>>@@ -1520,7 +1515,7 @@

>>     # i18n: "unstable" is a keyword

>>     getargs(x, 0, 0, _("unstable takes no arguments"))

>>     unstables = obsmod.getrevs(repo, 'unstable')

>>-    return baseset([r for r in subset if r in unstables])

>>+    return subset & unstables

>> 

>> 

>> def user(repo, subset, x):

>>@@ -2051,5 +2046,11 @@

>>             s = set(x)

>>         return baseset(self.set() - s)

>> 

>>+    def __and__(self, x):

>>+        s = self.set()

>>+        if isinstance(x, baseset):

>>+            x = x.set()

>>+        return baseset([y for y in s if y in x])

>>+

>> # tell hggettext to extract docstrings from these functions:

>> i18nfunctions = symbols.values()

>

>_______________________________________________

>Mercurial-devel mailing list

>Mercurial-devel@selenic.com

>http://selenic.com/mailman/listinfo/mercurial-devel
Matt Mackall - Feb. 5, 2014, 11:58 p.m.
On Mon, 2014-02-03 at 11:44 -0800, Lucas Moscovicz wrote:
> # HG changeset patch
> # User Lucas Moscovicz <lmoscovicz@fb.com>
> # Date 1390611464 28800
> #      Fri Jan 24 16:57:44 2014 -0800
> # Node ID c7a2e2891d64dc826a305983e14b678cb922f97b
> # Parent  f6b40a0e62bbdcfc8aaa10f0b678428809a8c729
> revset: added intersection to baseset class

These are queued for default, thanks.

Patch

diff --git a/mercurial/revset.py b/mercurial/revset.py
--- a/mercurial/revset.py
+++ b/mercurial/revset.py
@@ -402,8 +402,7 @@ 
             bmrevs = set()
             for bmrev in matchrevs:
                 bmrevs.add(repo[bmrev].rev())
-            s = subset.set()
-            return baseset([r for r in s if r in bmrevs])
+            return subset & bmrevs
 
     bms = set([repo[r].rev()
                for r in repo._bookmarks.values()])
@@ -450,7 +449,7 @@ 
     # i18n: "bumped" is a keyword
     getargs(x, 0, 0, _("bumped takes no arguments"))
     bumped = obsmod.getrevs(repo, 'bumped')
-    return baseset([r for r in subset if r in bumped])
+    return subset & bumped
 
 def bundle(repo, subset, x):
     """``bundle()``
@@ -462,7 +461,7 @@ 
         bundlerevs = repo.changelog.bundlerevs
     except AttributeError:
         raise util.Abort(_("no bundle provided - specify with -R"))
-    return baseset([r for r in subset if r in bundlerevs])
+    return subset & bundlerevs
 
 def checkstatus(repo, subset, pat, field):
     m = None
@@ -515,7 +514,7 @@ 
     """
     s = getset(repo, baseset(repo), x).set()
     cs = _children(repo, subset, s)
-    return baseset([r for r in subset if r in cs])
+    return subset & cs
 
 def closed(repo, subset, x):
     """``closed()``
@@ -680,7 +679,7 @@ 
     # i18n: "extinct" is a keyword
     getargs(x, 0, 0, _("extinct takes no arguments"))
     extincts = obsmod.getrevs(repo, 'extinct')
-    return baseset([r for r in subset if r in extincts])
+    return subset & extincts
 
 def extra(repo, subset, x):
     """``extra(label, [value])``
@@ -906,7 +905,7 @@ 
     # i18n: "hidden" is a keyword
     getargs(x, 0, 0, _("hidden takes no arguments"))
     hiddenrevs = repoview.filterrevs(repo, 'visible')
-    return baseset([r for r in subset if r in hiddenrevs])
+    return subset & hiddenrevs
 
 def keyword(repo, subset, x):
     """``keyword(string)``
@@ -1039,7 +1038,7 @@ 
     # i18n: "obsolete" is a keyword
     getargs(x, 0, 0, _("obsolete takes no arguments"))
     obsoletes = obsmod.getrevs(repo, 'obsolete')
-    return baseset([r for r in subset if r in obsoletes])
+    return subset & obsoletes
 
 def origin(repo, subset, x):
     """``origin([set])``
@@ -1106,8 +1105,7 @@ 
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.add(cl.parentrevs(r)[0])
-    s = subset.set()
-    return baseset([r for r in s if r in ps])
+    return subset & ps
 
 def p2(repo, subset, x):
     """``p2([set])``
@@ -1125,8 +1123,7 @@ 
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.add(cl.parentrevs(r)[1])
-    s = subset.set()
-    return baseset([r for r in s if r in ps])
+    return subset & ps
 
 def parents(repo, subset, x):
     """``parents([set])``
@@ -1134,14 +1131,13 @@ 
     """
     if x is None:
         ps = tuple(p.rev() for p in repo[x].parents())
-        return baseset([r for r in subset if r in ps])
+        return subset & ps
 
     ps = set()
     cl = repo.changelog
     for r in getset(repo, baseset(repo), x):
         ps.update(cl.parentrevs(r))
-    s = subset.set()
-    return baseset([r for r in s if r in ps])
+    return subset & ps
 
 def parentspec(repo, subset, x, n):
     """``set^0``
@@ -1166,8 +1162,7 @@ 
             parents = cl.parentrevs(r)
             if len(parents) > 1:
                 ps.add(parents[1])
-    s = subset.set()
-    return baseset([r for r in s if r in ps])
+    return subset & ps
 
 def present(repo, subset, x):
     """``present(set)``
@@ -1508,7 +1503,7 @@ 
             s = set([cl.rev(n) for t, n in repo.tagslist() if matcher(t)])
     else:
         s = set([cl.rev(n) for t, n in repo.tagslist() if t != 'tip'])
-    return baseset([r for r in subset if r in s])
+    return subset & s
 
 def tagged(repo, subset, x):
     return tag(repo, subset, x)
@@ -1520,7 +1515,7 @@ 
     # i18n: "unstable" is a keyword
     getargs(x, 0, 0, _("unstable takes no arguments"))
     unstables = obsmod.getrevs(repo, 'unstable')
-    return baseset([r for r in subset if r in unstables])
+    return subset & unstables
 
 
 def user(repo, subset, x):
@@ -2051,5 +2046,11 @@ 
             s = set(x)
         return baseset(self.set() - s)
 
+    def __and__(self, x):
+        s = self.set()
+        if isinstance(x, baseset):
+            x = x.set()
+        return baseset([y for y in s if y in x])
+
 # tell hggettext to extract docstrings from these functions:
 i18nfunctions = symbols.values()