##// END OF EJS Templates
Performance enhancements for manifest.add()...
mason@suse.com -
r644:6ebe1182 default
parent child Browse files
Show More
@@ -11,6 +11,7 b' from revlog import *'
11 11 from demandload import *
12 12 demandload(globals(), "re lock urllib urllib2 transaction time socket")
13 13 demandload(globals(), "tempfile httprangereader bdiff")
14 demandload(globals(), "bisect")
14 15
15 16 class filelog(revlog):
16 17 def __init__(self, opener, path):
@@ -124,16 +125,115 b' class manifest(revlog):'
124 125 else:
125 126 return mdiff.textdiff(a, b)
126 127
127 def add(self, map, flags, transaction, link, p1=None, p2=None):
128 files = map.keys()
129 files.sort()
128 def add(self, map, flags, transaction, link, p1=None, p2=None,changed=None):
129 # directly generate the mdiff delta from the data collected during
130 # the bisect loop below
131 def gendelta(delta):
132 i = 0
133 result = []
134 while i < len(delta):
135 start = delta[i][2]
136 end = delta[i][3]
137 l = delta[i][4]
138 if l == None:
139 l = ""
140 while i < len(delta) - 1 and start <= delta[i+1][2] and end >= delta[i+1][2]:
141 if delta[i+1][3] > end:
142 end = delta[i+1][3]
143 if delta[i+1][4]:
144 l += delta[i+1][4]
145 i += 1
146 result.append(struct.pack(">lll", start, end, len(l)) + l)
147 i += 1
148 return result
149
150 # apply the changes collected during the bisect loop to our addlist
151 def addlistdelta(addlist, delta):
152 # apply the deltas to the addlist. start from the bottom up
153 # so changes to the offsets don't mess things up.
154 i = len(delta)
155 while i > 0:
156 i -= 1
157 start = delta[i][0]
158 end = delta[i][1]
159 if delta[i][4]:
160 addlist[start:end] = [delta[i][4]]
161 else:
162 del addlist[start:end]
163 return addlist
164
165 # calculate the byte offset of the start of each line in the
166 # manifest
167 def calcoffsets(addlist):
168 offsets = [0] * (len(addlist) + 1)
169 offset = 0
170 i = 0
171 while i < len(addlist):
172 offsets[i] = offset
173 offset += len(addlist[i])
174 i += 1
175 offsets[i] = offset
176 return offsets
130 177
131 self.addlist = ["%s\000%s%s\n" %
132 (f, hex(map[f]), flags[f] and "x" or '')
133 for f in files]
178 # if we're using the listcache, make sure it is valid and
179 # parented by the same node we're diffing against
180 if not changed or not self.listcache or not p1 or self.mapcache[0] != p1:
181 files = map.keys()
182 files.sort()
183
184 self.addlist = ["%s\000%s%s\n" %
185 (f, hex(map[f]), flags[f] and "x" or '')
186 for f in files]
187 cachedelta = None
188 else:
189 addlist = self.listcache[1]
190
191 # find the starting offset for each line in the add list
192 offsets = calcoffsets(addlist)
193
194 # combine the changed lists into one list for sorting
195 work = [[x, 0] for x in changed[0]]
196 work[len(work):] = [[x, 1] for x in changed[1]]
197 work.sort()
198
199 delta = []
200 bs = 0
201
202 for w in work:
203 f = w[0]
204 # bs will either be the index of the item or the insertion point
205 bs = bisect.bisect(addlist, f, bs)
206 if bs < len(addlist):
207 fn = addlist[bs][:addlist[bs].index('\0')]
208 else:
209 fn = None
210 if w[1] == 0:
211 l = "%s\000%s%s\n" % (f, hex(map[f]), flags[f] and "x" or '')
212 else:
213 l = None
214 start = bs
215 if fn != f:
216 # item not found, insert a new one
217 end = bs
218 if w[1] == 1:
219 sys.stderr.write("failed to remove %s from manifest" % f)
220 sys.exit(1)
221 else:
222 # item is found, replace/delete the existing line
223 end = bs + 1
224 delta.append([start, end, offsets[start], offsets[end], l])
225
226 self.addlist = addlistdelta(addlist, delta)
227 if self.mapcache[0] == self.tip():
228 cachedelta = "".join(gendelta(delta))
229 else:
230 cachedelta = None
231
134 232 text = "".join(self.addlist)
135
136 n = self.addrevision(text, transaction, link, p1, p2)
233 if cachedelta and mdiff.patch(self.listcache[0], cachedelta) != text:
234 sys.stderr.write("manifest delta failure")
235 sys.exit(1)
236 n = self.addrevision(text, transaction, link, p1, p2, cachedelta)
137 237 self.mapcache = (n, map, flags)
138 238 self.listcache = (text, self.addlist)
139 239 self.addlist = None
@@ -669,7 +769,7 b' class localrepository:'
669 769 for f in remove:
670 770 if f in m1:
671 771 del m1[f]
672 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0])
772 mn = self.manifest.add(m1, mf1, tr, linkrev, c1[0], c2[0], (new,remove))
673 773
674 774 # add changeset
675 775 new = new.keys()
@@ -267,7 +267,7 b' class revlog:'
267 267 self.cache = (node, rev, text)
268 268 return text
269 269
270 def addrevision(self, text, transaction, link, p1=None, p2=None):
270 def addrevision(self, text, transaction, link, p1=None, p2=None, d=None):
271 271 if text is None: text = ""
272 272 if p1 is None: p1 = self.tip()
273 273 if p2 is None: p2 = nullid
@@ -284,8 +284,9 b' class revlog:'
284 284 base = self.base(t)
285 285 start = self.start(base)
286 286 end = self.end(t)
287 prev = self.revision(self.tip())
288 d = self.diff(prev, text)
287 if not d:
288 prev = self.revision(self.tip())
289 d = self.diff(prev, text)
289 290 data = compress(d)
290 291 dist = end - start + len(data)
291 292
General Comments 0
You need to be logged in to leave comments. Login now