comparison mercurial/manifest.py @ 17983:c64e646af81e

commit: increase perf by building a new addlist instead of editing the old one When commiting to a repo with lots of files (>170000), manifest.py:addlistdelta takes some time because it's editing a large array many times. Changing it to build a new array instead of editing the old one saves around 0.04 seconds on a 1.64 second commit. A 2.5% gain. The gain here is pretty minor, but it was blatantly at the top of the profiler report and the fix is straight forward. I tested it by comparing the arrays produced by the new and old logic while running all of the tests.
author Durham Goode <durham@fb.com>
date Mon, 19 Nov 2012 16:05:40 -0800
parents 72803c8edaa4
children a1141f04e368
comparison
equal deleted inserted replaced
17982:e06e9fd2d99f 17983:c64e646af81e
115 def add(self, map, transaction, link, p1=None, p2=None, 115 def add(self, map, transaction, link, p1=None, p2=None,
116 changed=None): 116 changed=None):
117 # apply the changes collected during the bisect loop to our addlist 117 # apply the changes collected during the bisect loop to our addlist
118 # return a delta suitable for addrevision 118 # return a delta suitable for addrevision
119 def addlistdelta(addlist, x): 119 def addlistdelta(addlist, x):
120 # start from the bottom up 120 # for large addlist arrays, building a new array is cheaper
121 # so changes to the offsets don't mess things up. 121 # than repeatedly modifying the existing one
122 for start, end, content in reversed(x): 122 currentposition = 0
123 newaddlist = array.array('c')
124
125 for start, end, content in x:
126 newaddlist += addlist[currentposition:start]
123 if content: 127 if content:
124 addlist[start:end] = array.array('c', content) 128 newaddlist += array.array('c', content)
125 else: 129
126 del addlist[start:end] 130 currentposition = end
127 return "".join(struct.pack(">lll", start, end, len(content)) 131
132 newaddlist += addlist[currentposition:]
133
134 deltatext = "".join(struct.pack(">lll", start, end, len(content))
128 + content for start, end, content in x) 135 + content for start, end, content in x)
136 return deltatext, newaddlist
129 137
130 def checkforbidden(l): 138 def checkforbidden(l):
131 for f in l: 139 for f in l:
132 if '\n' in f or '\r' in f: 140 if '\n' in f or '\r' in f:
133 raise error.RevlogError( 141 raise error.RevlogError(
192 dline = [l] 200 dline = [l]
193 201
194 if dstart is not None: 202 if dstart is not None:
195 delta.append([dstart, dend, "".join(dline)]) 203 delta.append([dstart, dend, "".join(dline)])
196 # apply the delta to the addlist, and get a delta for addrevision 204 # apply the delta to the addlist, and get a delta for addrevision
197 cachedelta = (self.rev(p1), addlistdelta(addlist, delta)) 205 deltatext, addlist = addlistdelta(addlist, delta)
206 cachedelta = (self.rev(p1), deltatext)
198 arraytext = addlist 207 arraytext = addlist
199 text = util.buffer(arraytext) 208 text = util.buffer(arraytext)
200 209
201 n = self.addrevision(text, transaction, link, p1, p2, cachedelta) 210 n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
202 self._mancache = (n, map, arraytext) 211 self._mancache = (n, map, arraytext)