[MERGE] binary search for 'date:' revision

Guillaume Pinot guillaume.pinot at tremplin-utc.net
Thu May 4 09:35:14 BST 2006


Guillaume Pinot <guillaume.pinot at tremplin-utc.net> writes:

> "Olaf Conradi" <oohlaf at gmail.com> writes:
> 
> > On 28/04/06, Guillaume Pinot <guillaume.pinot at tremplin-utc.net> wrote:
> > 
> > > I've changed the linear search for 'date:' revision to a binary
> > > search. It speedup commands like "bzr log -r date:yesterday" a
> > > lot.
> > >
> > > http://wwwlinux.utc.fr/~pinotgui/hack/bzr.dev.gp.binsearch/
> > 
> > Looks good, I like it (I also made a binsearch version, but using
> > bisect is better)
> > 
> > +1 if you add a NEWS entry
> 
> NEWS entry added.

I relanch this thread.

This patch speedup a lot revision date (5 min for bzr log -r
date:yesterday on bzr.dev, imediate with this patch).

I try to keep this branch mergable with bzr.dev. It's not up to date
merged, but it must merge without conflict.

What it the rule for the "+1" things?

Because it seems to be the desired way, here is the relevant patch
from the branch. (bzr diff -r -5..-2)

Thanks.

=== modified file 'a/NEWS'
--- a/NEWS      
+++ b/NEWS      
@@ -97,6 +97,8 @@
 
     * Hitting CTRL-C while doing an SFTP push will no longer cause
       stale locks
       to be left in the SFTP repository. (Robert Collins, Martin
       Pool).
+
+    * Speedup improvement for 'date:'-revision search. (Guillaume Pinot).
 
   CHANGES:
 

=== modified file 'a/bzrlib/revisionspec.py'
--- a/bzrlib/revisionspec.py    
+++ b/bzrlib/revisionspec.py    
@@ -17,6 +17,7 @@
 
 import datetime
 import re
+import bisect
 from bzrlib.errors import BzrError, NoSuchRevision, NoCommits
 
 _marker = []
@@ -248,6 +249,18 @@
 SPEC_TYPES.append(RevisionSpec_tag)
 
 
+class RevisionSpec_revs:
+    def __init__(self, revs, branch):
+        self.revs = revs
+        self.branch = branch
+    def __getitem__(self, index):
+        r = self.branch.repository.get_revision(self.revs[index])
+        # TODO: Handle timezone.
+        return datetime.datetime.fromtimestamp(r.timestamp)
+    def __len__(self):
+        return len(self.revs)
+
+
 class RevisionSpec_date(RevisionSpec):
     prefix = 'date:'
     _date_re = re.compile(
@@ -295,14 +308,12 @@
 
             dt = datetime.datetime(year=year, month=month, day=day,
                     hour=hour, minute=minute, second=second)
-        first = dt
-        for i in range(len(revs)):
-            r = branch.repository.get_revision(revs[i])
-            # TODO: Handle timezone.
-            dt = datetime.datetime.fromtimestamp(r.timestamp)
-            if first <= dt:
-                return RevisionInfo(branch, i+1)
-        return RevisionInfo(branch, None)
+
+        rev = bisect.bisect(RevisionSpec_revs(revs, branch), dt)
+        if rev == len(revs):
+            return RevisionInfo(branch, None)
+        else:
+            return RevisionInfo(branch, rev + 1)
 
 SPEC_TYPES.append(RevisionSpec_date)
 

=== modified file 'a/bzrlib/tests/test_revisionnamespaces.py'
--- a/bzrlib/tests/test_revisionnamespaces.py   
+++ b/bzrlib/tests/test_revisionnamespaces.py   
@@ -54,6 +54,8 @@
                           (1, 'a at r-0-1'))
         self.assertEquals(RevisionSpec('before:date:today').in_history(b),
                           (1, 'a at r-0-1'))
+        self.assertRaises(NoSuchRevision,
+                          RevisionSpec('date:tomorrow').in_history, b)
 
         self.assertEquals(RevisionSpec('last:1').in_history(b),
                           (3, 'a at r-0-3'))






More information about the bazaar mailing list