1
Hello Aaron. Here's yet another bug report we received at Debian's BTS. :)
5
----- Forwarded message from Loïc Minier <lool@dooz.org> -----
7
From: Loïc Minier <lool@dooz.org>
8
To: Debian Bug Tracking System <submit@bugs.debian.org>
9
Date: Mon, 30 Jul 2007 12:27:11 +0200
10
Subject: Bug#435240: multi-pull is slow because it doesn't reuse connections
19
multi-pull is relatively slow because it opens a connection for each
20
branch (especially ssh connections are slow). I'm attaching a patch to
21
reuse the connection for all branches with the same URL base. I hope
22
it's not so ugly that you poke yourself an eye out.
24
The old behavior isn't available anymore with the patch, but perhaps
25
this is a problem for some transports? I have no idea.
29
-- System Information:
30
Debian Release: lenny/sid
32
APT policy: (500, 'unstable'), (1, 'experimental')
33
Architecture: i386 (i686)
35
Kernel: Linux 2.6.22-1-686 (SMP w/2 CPU cores)
36
Locale: LANG=fr_FR.UTF-8, LC_CTYPE=fr_FR.UTF-8 (charmap=UTF-8)
37
Shell: /bin/sh linked to /bin/dash
39
Versions of packages bzrtools depends on:
40
ii bzr 0.18-1 Bazaar, the next-generation distri
41
ii patch 2.5.9-4 Apply a diff file to an original
42
ii python 2.4.4-6 An interactive high-level object-o
43
ii python-central 0.5.14 register and build utility for Pyt
45
Versions of packages bzrtools recommends:
46
ii graphviz 2.12-3 rich set of graph drawing tools
47
ii rsync 2.6.9-3 fast remote file copy program (lik
49
-- no debconf information
54
--- bzrtools-0.18.0/debian/changelog
55
+++ bzrtools-0.18.0/debian/changelog
57
+bzrtools (0.18.0-1.1) UNRELEASED; urgency=low
59
+ * Non-maintainer upload.
60
+ * Group branches by URL base and reuse one transport per URL base to avoid
61
+ reopening a connection for each pull in multi-pull.
63
+ -- Loic Minier <lool@dooz.org> Mon, 30 Jul 2007 12:06:43 +0200
65
bzrtools (0.18.0-1) unstable; urgency=low
68
--- bzrtools-0.18.0.orig/__init__.py
69
+++ bzrtools-0.18.0/__init__.py
72
print "Can't list this type of location."
74
- for branch, wt in iter_branch_tree(t):
79
- parent = branch.get_parent()
86
- if base.startswith(t.base):
87
- relpath = base[len(t.base):].rstrip('/')
90
- print "Pulling %s from %s" % (relpath, parent)
92
- pullable.pull(Branch.open(parent))
93
- except Exception, e:
95
+ print "Grouping branches by URL"
96
+ by_urlbase = pullable_infos_by_urlbase(t)
97
+ for urlbase in by_urlbase:
98
+ print "Processing branches for %s/" % urlbase
99
+ urlbase_transport = get_transport(urlbase)
100
+ for pi in by_urlbase[urlbase]:
101
+ pullable = pi.get_pullable()
102
+ relpath = get_relpath(t.base, pi.get_base())
103
+ parent = pi.get_parent()
104
+ from bzrtools import bzrdir_from_transport
105
+ pull_transport = urlbase_transport.clone(get_relpath(urlbase, parent))
106
+ bzrdir = bzrdir_from_transport(pull_transport)
107
+ pull_branch = bzrdir.open_branch()
108
+ print "Pulling %s from %s" % (relpath, parent)
110
+ pullable.pull(pull_branch)
111
+ except Exception, e:
115
+def get_relpath(base, path):
116
+ if path.startswith(base):
117
+ return path[len(base):].rstrip('/')
123
+ def __init__(self, branch, wt):
124
+ self.branch = branch
127
+ def get_pullable(self):
128
+ if self.wt is None:
132
+ def get_parent(self):
133
+ return self.branch.get_parent()
135
+ def get_base(self):
136
+ if self.wt is not None:
137
+ return self.wt.basedir
138
+ return self.branch.base
140
+ def get_urlbase(self):
142
+ # always matches at least the empty string
143
+ urlbase_pattern = re.compile("^(([^:]*://)?([^/]*))")
144
+ return urlbase_pattern.match(self.get_parent()).groups()[0]
147
+def pullable_infos_by_urlbase(t):
148
+ pullables_by_urlbase = {}
149
+ from bzrtools import iter_branch_tree
150
+ for branch, wt in iter_branch_tree(t):
151
+ parent = branch.get_parent()
154
+ pullable_info = PullableInfo(branch, wt)
155
+ urlbase = pullable_info.get_urlbase()
157
+ pullables_by_urlbase[urlbase] += (pullable_info, )
159
+ pullables_by_urlbase[urlbase] = (pullable_info, )
160
+ return pullables_by_urlbase
163
class cmd_branch_mark(bzrlib.commands.Command):