Mercurial > hg-stable
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) |