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)