Mercurial > hg > mercurial-crew-with-dirclash
comparison mercurial/dirstate.py @ 5327:f46ab9cacd3c
dirstate: speed up read and write
read:
- single call to len(st)
- fewer assignments for position tracking
- don't split apart tuple from unpack
- use a literal for the unpack spec
write:
- localize variables and functions
- avoid copied function call
- use % for string concatenation
author | Matt Mackall <mpm@selenic.com> |
---|---|
date | Mon, 24 Sep 2007 12:41:54 -0500 |
parents | 319c09685f30 |
children | 5105b119edd2 |
comparison
equal
deleted
inserted
replaced
5326:319c09685f30 | 5327:f46ab9cacd3c |
---|---|
139 | 139 |
140 # deref fields so they will be local in loop | 140 # deref fields so they will be local in loop |
141 dmap = self._map | 141 dmap = self._map |
142 copymap = self._copymap | 142 copymap = self._copymap |
143 unpack = struct.unpack | 143 unpack = struct.unpack |
144 | |
145 pos = 40 | |
146 e_size = struct.calcsize(_format) | 144 e_size = struct.calcsize(_format) |
147 | 145 pos1 = 40 |
148 while pos < len(st): | 146 l = len(st) |
149 newpos = pos + e_size | 147 |
150 e = unpack(_format, st[pos:newpos]) | 148 # the inner loop |
151 l = e[4] | 149 while pos1 < l: |
152 pos = newpos | 150 pos2 = pos1 + e_size |
153 newpos = pos + l | 151 e = unpack(">cllll", st[pos1:pos2]) # a literal here is faster |
154 f = st[pos:newpos] | 152 pos1 = pos2 + e[4] |
153 f = st[pos2:pos1] | |
155 if '\0' in f: | 154 if '\0' in f: |
156 f, c = f.split('\0') | 155 f, c = f.split('\0') |
157 copymap[f] = c | 156 copymap[f] = c |
158 dmap[f] = e[:4] | 157 dmap[f] = e # we hold onto e[4] because making a subtuple is slow |
159 pos = newpos | |
160 | 158 |
161 def invalidate(self): | 159 def invalidate(self): |
162 for a in "_map _copymap _branch _pl _dirs _ignore".split(): | 160 for a in "_map _copymap _branch _pl _dirs _ignore".split(): |
163 if a in self.__dict__: | 161 if a in self.__dict__: |
164 delattr(self, a) | 162 delattr(self, a) |
214 | 212 |
215 def normal(self, f): | 213 def normal(self, f): |
216 'mark a file normal and clean' | 214 'mark a file normal and clean' |
217 self._dirty = True | 215 self._dirty = True |
218 s = os.lstat(self._join(f)) | 216 s = os.lstat(self._join(f)) |
219 self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime) | 217 self._map[f] = ('n', s.st_mode, s.st_size, s.st_mtime, 0) |
220 if self._copymap.has_key(f): | 218 if self._copymap.has_key(f): |
221 del self._copymap[f] | 219 del self._copymap[f] |
222 | 220 |
223 def normallookup(self, f): | 221 def normallookup(self, f): |
224 'mark a file normal, but possibly dirty' | 222 'mark a file normal, but possibly dirty' |
225 self._dirty = True | 223 self._dirty = True |
226 self._map[f] = ('n', 0, -1, -1) | 224 self._map[f] = ('n', 0, -1, -1, 0) |
227 if f in self._copymap: | 225 if f in self._copymap: |
228 del self._copymap[f] | 226 del self._copymap[f] |
229 | 227 |
230 def normaldirty(self, f): | 228 def normaldirty(self, f): |
231 'mark a file normal, but dirty' | 229 'mark a file normal, but dirty' |
232 self._dirty = True | 230 self._dirty = True |
233 self._map[f] = ('n', 0, -2, -1) | 231 self._map[f] = ('n', 0, -2, -1, 0) |
234 if f in self._copymap: | 232 if f in self._copymap: |
235 del self._copymap[f] | 233 del self._copymap[f] |
236 | 234 |
237 def add(self, f): | 235 def add(self, f): |
238 'mark a file added' | 236 'mark a file added' |
239 self._dirty = True | 237 self._dirty = True |
240 self._incpathcheck(f) | 238 self._incpathcheck(f) |
241 self._map[f] = ('a', 0, -1, -1) | 239 self._map[f] = ('a', 0, -1, -1, 0) |
242 if f in self._copymap: | 240 if f in self._copymap: |
243 del self._copymap[f] | 241 del self._copymap[f] |
244 | 242 |
245 def remove(self, f): | 243 def remove(self, f): |
246 'mark a file removed' | 244 'mark a file removed' |
247 self._dirty = True | 245 self._dirty = True |
248 self._map[f] = ('r', 0, 0, 0) | 246 self._map[f] = ('r', 0, 0, 0, 0) |
249 self._decpath(f) | 247 self._decpath(f) |
250 if f in self._copymap: | 248 if f in self._copymap: |
251 del self._copymap[f] | 249 del self._copymap[f] |
252 | 250 |
253 def merge(self, f): | 251 def merge(self, f): |
254 'mark a file merged' | 252 'mark a file merged' |
255 self._dirty = True | 253 self._dirty = True |
256 s = os.lstat(self._join(f)) | 254 s = os.lstat(self._join(f)) |
257 self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime) | 255 self._map[f] = ('m', s.st_mode, s.st_size, s.st_mtime, 0) |
258 if f in self._copymap: | 256 if f in self._copymap: |
259 del self._copymap[f] | 257 del self._copymap[f] |
260 | 258 |
261 def forget(self, f): | 259 def forget(self, f): |
262 'forget a file' | 260 'forget a file' |
275 | 273 |
276 def rebuild(self, parent, files): | 274 def rebuild(self, parent, files): |
277 self.clear() | 275 self.clear() |
278 for f in files: | 276 for f in files: |
279 if files.execf(f): | 277 if files.execf(f): |
280 self._map[f] = ('n', 0777, -1, 0) | 278 self._map[f] = ('n', 0777, -1, 0, 0) |
281 else: | 279 else: |
282 self._map[f] = ('n', 0666, -1, 0) | 280 self._map[f] = ('n', 0666, -1, 0, 0) |
283 self._pl = (parent, nullid) | 281 self._pl = (parent, nullid) |
284 self._dirty = True | 282 self._dirty = True |
285 | 283 |
286 def write(self): | 284 def write(self): |
287 if not self._dirty: | 285 if not self._dirty: |
288 return | 286 return |
289 cs = cStringIO.StringIO() | 287 cs = cStringIO.StringIO() |
290 cs.write("".join(self._pl)) | 288 copymap = self._copymap |
289 pack = struct.pack | |
290 write = cs.write | |
291 write("".join(self._pl)) | |
291 for f, e in self._map.iteritems(): | 292 for f, e in self._map.iteritems(): |
292 c = self.copied(f) | 293 if f in copymap: |
293 if c: | 294 f = "%s\0%s" % (f, copymap[f]) |
294 f = f + "\0" + c | 295 e = pack(_format, e[0], e[1], e[2], e[3], len(f)) |
295 e = struct.pack(_format, e[0], e[1], e[2], e[3], len(f)) | 296 write(e) |
296 cs.write(e) | 297 write(f) |
297 cs.write(f) | |
298 st = self._opener("dirstate", "w", atomictemp=True) | 298 st = self._opener("dirstate", "w", atomictemp=True) |
299 st.write(cs.getvalue()) | 299 st.write(cs.getvalue()) |
300 st.rename() | 300 st.rename() |
301 self._dirty = self._dirtypl = False | 301 self._dirty = self._dirtypl = False |
302 | 302 |
508 dadd = deleted.append | 508 dadd = deleted.append |
509 cadd = clean.append | 509 cadd = clean.append |
510 | 510 |
511 for src, fn, st in self.statwalk(files, match, ignored=list_ignored): | 511 for src, fn, st in self.statwalk(files, match, ignored=list_ignored): |
512 if fn in dmap: | 512 if fn in dmap: |
513 type_, mode, size, time = dmap[fn] | 513 type_, mode, size, time, foo = dmap[fn] |
514 else: | 514 else: |
515 if list_ignored and self._ignore(fn): | 515 if list_ignored and self._ignore(fn): |
516 iadd(fn) | 516 iadd(fn) |
517 else: | 517 else: |
518 uadd(fn) | 518 uadd(fn) |