comparison mercurial/revlog.py @ 76:d993ebd69d28

Add lazy{parser,index,map} to speed up processing of index files
author mpm@selenic.com
date Tue, 17 May 2005 00:33:22 -0800
parents ee1cbe841e01
children bed15e766511
comparison
equal deleted inserted replaced
75:b942bbe4bb84 76:d993ebd69d28
26 return sha.sha(l[0] + l[1] + text).digest() 26 return sha.sha(l[0] + l[1] + text).digest()
27 27
28 nullid = "\0" * 20 28 nullid = "\0" * 20
29 indexformat = ">4l20s20s20s" 29 indexformat = ">4l20s20s20s"
30 30
31 class lazyparser:
32 def __init__(self, data):
33 self.data = data
34 self.s = struct.calcsize(indexformat)
35 self.l = len(data)/self.s
36 self.index = [None] * self.l
37 self.map = {nullid: -1}
38
39 if 0:
40 n = 0
41 i = self.data
42 s = struct.calcsize(indexformat)
43 for f in xrange(0, len(i), s):
44 # offset, size, base, linkrev, p1, p2, nodeid
45 e = struct.unpack(indexformat, i[f:f + s])
46 self.map[e[6]] = n
47 self.index.append(e)
48 n += 1
49
50 def load(self, pos):
51 block = pos / 1000
52 i = block * 1000
53 end = min(self.l, i + 1000)
54 while i < end:
55 d = self.data[i * self.s: (i + 1) * self.s]
56 e = struct.unpack(indexformat, d)
57 self.index[i] = e
58 self.map[e[6]] = i
59 i += 1
60
61 class lazyindex:
62 def __init__(self, parser):
63 self.p = parser
64 def __len__(self):
65 return len(self.p.index)
66 def __getitem__(self, pos):
67 i = self.p.index[pos]
68 if not i:
69 self.p.load(pos)
70 return self.p.index[pos]
71 return i
72 def append(self, e):
73 self.p.index.append(e)
74
75 class lazymap:
76 def __init__(self, parser):
77 self.p = parser
78 def load(self, key):
79 n = self.p.data.find(key)
80 if n < 0: raise KeyError(key)
81 pos = n / self.p.s
82 self.p.load(pos)
83 def __contains__(self, key):
84 try:
85 self.p.map[key]
86 return True
87 except KeyError:
88 return False
89 def __getitem__(self, key):
90 try:
91 return self.p.map[key]
92 except KeyError:
93 self.load(key)
94 return self.p.map[key]
95 def __setitem__(self, key, val):
96 self.p.map[key] = val
97
31 class revlog: 98 class revlog:
32 def __init__(self, opener, indexfile, datafile): 99 def __init__(self, opener, indexfile, datafile):
33 self.indexfile = indexfile 100 self.indexfile = indexfile
34 self.datafile = datafile 101 self.datafile = datafile
35 self.index = []
36 self.opener = opener 102 self.opener = opener
37 self.cache = None 103 self.cache = None
38 # read the whole index for now, handle on-demand later 104 # read the whole index for now, handle on-demand later
39 try: 105 try:
40 n = 0
41 i = self.opener(self.indexfile).read() 106 i = self.opener(self.indexfile).read()
42 s = struct.calcsize(indexformat)
43
44 # preallocate arrays
45 l = len(i)/s
46 self.index = [None] * l
47 m = [None] * l
48
49 for f in xrange(0, len(i), s):
50 # offset, size, base, linkrev, p1, p2, nodeid
51 e = struct.unpack(indexformat, i[f:f + s])
52 self.index[n] = e
53 m[n] = (e[6], n)
54 n += 1
55
56 self.nodemap = dict(m)
57 except IOError: 107 except IOError:
58 self.nodemap = {} 108 i = ""
59 self.nodemap[nullid] = -1 109 parser = lazyparser(i)
110 self.index = lazyindex(parser)
111 self.nodemap = lazymap(parser)
60 112
61 def tip(self): return self.node(len(self.index) - 1) 113 def tip(self): return self.node(len(self.index) - 1)
62 def count(self): return len(self.index) 114 def count(self): return len(self.index)
63 def node(self, rev): return (rev < 0) and nullid or self.index[rev][6] 115 def node(self, rev): return (rev < 0) and nullid or self.index[rev][6]
64 def rev(self, node): return self.nodemap[node] 116 def rev(self, node): return self.nodemap[node]