Submitter | Durham Goode |
---|---|
Date | Sept. 30, 2014, 1:12 a.m. |
Message ID | <93be919300f04bfd26fd.1412039531@dev2000.prn2.facebook.com> |
Download | mbox | patch |
Permalink | /patch/6031/ |
State | Superseded |
Headers | show |
Comments
On 9/29/14, 6:12 PM, Durham Goode wrote: > # HG changeset patch > # User Durham Goode <durham@fb.com> > # Date 1412036731 25200 > # Mon Sep 29 17:25:31 2014 -0700 > # Node ID 93be919300f04bfd26fd5294499fb62c96ba7f93 > # Parent c6129c781a9f11be26191e64dcebf8d539c8c76a > revset: add __length_hint__ to smart classes > > This adds a __length_hint__ to the smart revset classes so we can optimize at > runtime to avoid things like iterating over the large set and checking > containment against the small set when doing 'X & Y'. > > diff --git a/mercurial/revset.py b/mercurial/revset.py > --- a/mercurial/revset.py > +++ b/mercurial/revset.py > @@ -2204,6 +2204,9 @@ class baseset(list): > super(baseset, self).__init__(data) > self._set = None > > + def __length_hint__(self): > + return len(self) > + > def ascending(self): > """Sorts the set in ascending order (in place). > > @@ -2376,6 +2379,9 @@ class lazyset(object): > l = baseset([r for r in self]) > return len(l) > > + def __length_hint__(self): > + return self._subset.__length_hint__() > + I'm not 100% satisfied with this stuff. _subset is not guaranteed to be a smart set, and therefore might not even implement __length_hint__. But to fix it would require auditing every revset to ensure that subsets are always one of our smartsets.
On 9/29/14, 6:47 PM, Durham Goode wrote: > > On 9/29/14, 6:12 PM, Durham Goode wrote: >> # HG changeset patch >> # User Durham Goode <durham@fb.com> >> # Date 1412036731 25200 >> # Mon Sep 29 17:25:31 2014 -0700 >> # Node ID 93be919300f04bfd26fd5294499fb62c96ba7f93 >> # Parent c6129c781a9f11be26191e64dcebf8d539c8c76a >> revset: add __length_hint__ to smart classes >> >> This adds a __length_hint__ to the smart revset classes so we can >> optimize at >> runtime to avoid things like iterating over the large set and checking >> containment against the small set when doing 'X & Y'. >> >> diff --git a/mercurial/revset.py b/mercurial/revset.py >> --- a/mercurial/revset.py >> +++ b/mercurial/revset.py >> @@ -2204,6 +2204,9 @@ class baseset(list): >> super(baseset, self).__init__(data) >> self._set = None >> + def __length_hint__(self): >> + return len(self) >> + >> def ascending(self): >> """Sorts the set in ascending order (in place). >> @@ -2376,6 +2379,9 @@ class lazyset(object): >> l = baseset([r for r in self]) >> return len(l) >> + def __length_hint__(self): >> + return self._subset.__length_hint__() >> + > I'm not 100% satisfied with this stuff. _subset is not guaranteed to > be a smart set, and therefore might not even implement > __length_hint__. But to fix it would require auditing every revset to > ensure that subsets are always one of our smartsets. I've sent a V2 that addresses this issue.
Patch
diff --git a/mercurial/revset.py b/mercurial/revset.py --- a/mercurial/revset.py +++ b/mercurial/revset.py @@ -2204,6 +2204,9 @@ class baseset(list): super(baseset, self).__init__(data) self._set = None + def __length_hint__(self): + return len(self) + def ascending(self): """Sorts the set in ascending order (in place). @@ -2376,6 +2379,9 @@ class lazyset(object): l = baseset([r for r in self]) return len(l) + def __length_hint__(self): + return self._subset.__length_hint__() + def __getitem__(self, x): # Basic implementation to be changed in future patches. l = baseset([r for r in self]) @@ -2478,6 +2484,9 @@ class _addset(_orderedsetmixin): def __len__(self): return len(self._list) + def __length_hint__(self): + return self._r1.__length_hint__() + self._r2.__length_hint__() + @util.propertycache def _list(self): if not self._genlist: @@ -2688,6 +2697,11 @@ class _generatorset(object): def set(self): return self + def __length_hint__(self): + if util.safehasattr(self._gen, '__length_hint__'): + return self._gen.__length_hint__() + return sys.maxint + def sort(self, reverse=False): if not self._finished: for i in self: @@ -2800,6 +2814,9 @@ class _spanset(_orderedsetmixin): for r in iterrange: yield r + def __length_hint__(self): + return abs(self._start - self._end) + def __contains__(self, rev): start = self._start end = self._end