Mercurial > public > mercurial-scm > hg-stable
comparison mercurial/revlog.py @ 2255:3f38e872f39a
Reduce ram used for very large inlined index files
During a clone, an inline index is not converted to a split index
file until the very end. When the conversion happens, the index
can be very large, and the inline index loading functions always load
the entire index file into ram.
This changes the revlog code to read the index in smaller chunks.
author | mason@suse.com |
---|---|
date | Wed, 10 May 2006 15:26:56 -0700 |
parents | 45aef5ddcdbe |
children | 854954fd410a |
comparison
equal
deleted
inserted
replaced
2254:827fcfe88b14 | 2255:3f38e872f39a |
---|---|
374 # big index, let's parse it on demand | 374 # big index, let's parse it on demand |
375 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset) | 375 parser = lazyparser(f, st.st_size, self.indexformat, shaoffset) |
376 self.index = lazyindex(parser) | 376 self.index = lazyindex(parser) |
377 self.nodemap = lazymap(parser) | 377 self.nodemap = lazymap(parser) |
378 else: | 378 else: |
379 i = f.read() | 379 self.parseindex(f, st) |
380 self.parseindex(i) | |
381 if self.inlinedata(): | |
382 # we've already got the entire data file read in, save it | |
383 # in the chunk data | |
384 self.chunkcache = (0, i) | |
385 if self.version != REVLOGV0: | 380 if self.version != REVLOGV0: |
386 e = list(self.index[0]) | 381 e = list(self.index[0]) |
387 type = self.ngtype(e[0]) | 382 type = self.ngtype(e[0]) |
388 e[0] = self.offset_type(0, type) | 383 e[0] = self.offset_type(0, type) |
389 self.index[0] = e | 384 self.index[0] = e |
390 else: | 385 else: |
391 self.nodemap = { nullid: -1} | 386 self.nodemap = { nullid: -1} |
392 self.index = [] | 387 self.index = [] |
393 | 388 |
394 | 389 |
395 def parseindex(self, data): | 390 def parseindex(self, fp, st): |
396 s = struct.calcsize(self.indexformat) | 391 s = struct.calcsize(self.indexformat) |
397 l = len(data) | |
398 self.index = [] | 392 self.index = [] |
399 self.nodemap = {nullid: -1} | 393 self.nodemap = {nullid: -1} |
400 inline = self.inlinedata() | 394 inline = self.inlinedata() |
401 off = 0 | |
402 n = 0 | 395 n = 0 |
403 while off < l: | 396 leftover = None |
404 e = struct.unpack(self.indexformat, data[off:off + s]) | 397 while True: |
405 self.index.append(e) | 398 if st: |
406 self.nodemap[e[-1]] = n | 399 data = fp.read(65536) |
407 n += 1 | 400 else: |
408 off += s | 401 # hack for httprangereader, it doesn't do partial reads well |
409 if inline: | 402 data = fp.read() |
410 off += e[1] | 403 if not data: |
404 break | |
405 if n == 0 and self.inlinedata(): | |
406 # cache the first chunk | |
407 self.chunkcache = (0, data) | |
408 off = 0 | |
409 l = len(data) | |
410 while off < l: | |
411 if l - off < s: | |
412 leftover = data[off:] | |
413 break | |
414 if leftover: | |
415 cur = leftover + data[off:off + s - len(leftover)] | |
416 off += s - len(leftover) | |
417 leftover = None | |
418 else: | |
419 cur = data[off:off + s] | |
420 off += s | |
421 e = struct.unpack(self.indexformat, cur) | |
422 self.index.append(e) | |
423 self.nodemap[e[-1]] = n | |
424 n += 1 | |
425 if inline: | |
426 off += e[1] | |
427 if off > l: | |
428 # some things don't seek well, just read it | |
429 fp.read(off - l) | |
430 if not st: | |
431 break | |
432 | |
411 | 433 |
412 def ngoffset(self, q): | 434 def ngoffset(self, q): |
413 if q & 0xFFFF: | 435 if q & 0xFFFF: |
414 raise RevlogError(_('%s: incompatible revision flag %x') % | 436 raise RevlogError(_('%s: incompatible revision flag %x') % |
415 (self.indexfile, q)) | 437 (self.indexfile, q)) |