##// 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 from demandload import *
11 from demandload import *
12 demandload(globals(), "re lock urllib urllib2 transaction time socket")
12 demandload(globals(), "re lock urllib urllib2 transaction time socket")
13 demandload(globals(), "tempfile httprangereader bdiff")
13 demandload(globals(), "tempfile httprangereader bdiff")
14 demandload(globals(), "bisect")
14
15
15 class filelog(revlog):
16 class filelog(revlog):
16 def __init__(self, opener, path):
17 def __init__(self, opener, path):
@@ -124,16 +125,115 b' class manifest(revlog):'
124 else:
125 else:
125 return mdiff.textdiff(a, b)
126 return mdiff.textdiff(a, b)
126
127
127 def add(self, map, flags, transaction, link, p1=None, p2=None):
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
177
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:
128 files = map.keys()
181 files = map.keys()
129 files.sort()
182 files.sort()
130
183
131 self.addlist = ["%s\000%s%s\n" %
184 self.addlist = ["%s\000%s%s\n" %
132 (f, hex(map[f]), flags[f] and "x" or '')
185 (f, hex(map[f]), flags[f] and "x" or '')
133 for f in files]
186 for f in files]
134 text = "".join(self.addlist)
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
135
201
136 n = self.addrevision(text, transaction, link, p1, p2)
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
232 text = "".join(self.addlist)
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 self.mapcache = (n, map, flags)
237 self.mapcache = (n, map, flags)
138 self.listcache = (text, self.addlist)
238 self.listcache = (text, self.addlist)
139 self.addlist = None
239 self.addlist = None
@@ -669,7 +769,7 b' class localrepository:'
669 for f in remove:
769 for f in remove:
670 if f in m1:
770 if f in m1:
671 del m1[f]
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 # add changeset
774 # add changeset
675 new = new.keys()
775 new = new.keys()
@@ -267,7 +267,7 b' class revlog:'
267 self.cache = (node, rev, text)
267 self.cache = (node, rev, text)
268 return text
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 if text is None: text = ""
271 if text is None: text = ""
272 if p1 is None: p1 = self.tip()
272 if p1 is None: p1 = self.tip()
273 if p2 is None: p2 = nullid
273 if p2 is None: p2 = nullid
@@ -284,6 +284,7 b' class revlog:'
284 base = self.base(t)
284 base = self.base(t)
285 start = self.start(base)
285 start = self.start(base)
286 end = self.end(t)
286 end = self.end(t)
287 if not d:
287 prev = self.revision(self.tip())
288 prev = self.revision(self.tip())
288 d = self.diff(prev, text)
289 d = self.diff(prev, text)
289 data = compress(d)
290 data = compress(d)
General Comments 0
You need to be logged in to leave comments. Login now