comparison mercurial/revlog.py @ 33392:ac6446611ad2

revlog: use struct.Struct instances for slight performance wins Differential Revision: https://phab.mercurial-scm.org/D32
author Alex Gaynor <agaynor@mozilla.com>
date Mon, 10 Jul 2017 16:41:13 -0400
parents 943b8c37f49d
children 9180f8f593f3
comparison
equal deleted inserted replaced
33391:943b8c37f49d 33392:ac6446611ad2
42 util, 42 util,
43 ) 43 )
44 44
45 parsers = policy.importmod(r'parsers') 45 parsers = policy.importmod(r'parsers')
46 46
47 _pack = struct.pack
48 _unpack = struct.unpack
49 # Aliased for performance. 47 # Aliased for performance.
50 _zlibdecompress = zlib.decompress 48 _zlibdecompress = zlib.decompress
51 49
52 # revlog header flags 50 # revlog header flags
53 REVLOGV0 = 0 51 REVLOGV0 = 0
169 # 4 bytes: base rev 167 # 4 bytes: base rev
170 # 4 bytes: link rev 168 # 4 bytes: link rev
171 # 20 bytes: parent 1 nodeid 169 # 20 bytes: parent 1 nodeid
172 # 20 bytes: parent 2 nodeid 170 # 20 bytes: parent 2 nodeid
173 # 20 bytes: nodeid 171 # 20 bytes: nodeid
174 indexformatv0 = ">4l20s20s20s" 172 indexformatv0 = struct.Struct(">4l20s20s20s")
173 indexformatv0_pack = indexformatv0.pack
174 indexformatv0_unpack = indexformatv0.unpack
175 175
176 class revlogoldio(object): 176 class revlogoldio(object):
177 def __init__(self): 177 def __init__(self):
178 self.size = struct.calcsize(indexformatv0) 178 self.size = indexformatv0.size
179 179
180 def parseindex(self, data, inline): 180 def parseindex(self, data, inline):
181 s = self.size 181 s = self.size
182 index = [] 182 index = []
183 nodemap = {nullid: nullrev} 183 nodemap = {nullid: nullrev}
184 n = off = 0 184 n = off = 0
185 l = len(data) 185 l = len(data)
186 while off + s <= l: 186 while off + s <= l:
187 cur = data[off:off + s] 187 cur = data[off:off + s]
188 off += s 188 off += s
189 e = _unpack(indexformatv0, cur) 189 e = indexformatv0_unpack(cur)
190 # transform to revlogv1 format 190 # transform to revlogv1 format
191 e2 = (offset_type(e[0], 0), e[1], -1, e[2], e[3], 191 e2 = (offset_type(e[0], 0), e[1], -1, e[2], e[3],
192 nodemap.get(e[4], nullrev), nodemap.get(e[5], nullrev), e[6]) 192 nodemap.get(e[4], nullrev), nodemap.get(e[5], nullrev), e[6])
193 index.append(e2) 193 index.append(e2)
194 nodemap[e[6]] = n 194 nodemap[e[6]] = n
202 def packentry(self, entry, node, version, rev): 202 def packentry(self, entry, node, version, rev):
203 if gettype(entry[0]): 203 if gettype(entry[0]):
204 raise RevlogError(_('index entry flags need revlog version 1')) 204 raise RevlogError(_('index entry flags need revlog version 1'))
205 e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4], 205 e2 = (getoffset(entry[0]), entry[1], entry[3], entry[4],
206 node(entry[5]), node(entry[6]), entry[7]) 206 node(entry[5]), node(entry[6]), entry[7])
207 return _pack(indexformatv0, *e2) 207 return indexformatv0_pack(*e2)
208 208
209 # index ng: 209 # index ng:
210 # 6 bytes: offset 210 # 6 bytes: offset
211 # 2 bytes: flags 211 # 2 bytes: flags
212 # 4 bytes: compressed length 212 # 4 bytes: compressed length
214 # 4 bytes: base rev 214 # 4 bytes: base rev
215 # 4 bytes: link rev 215 # 4 bytes: link rev
216 # 4 bytes: parent 1 rev 216 # 4 bytes: parent 1 rev
217 # 4 bytes: parent 2 rev 217 # 4 bytes: parent 2 rev
218 # 32 bytes: nodeid 218 # 32 bytes: nodeid
219 indexformatng = ">Qiiiiii20s12x" 219 indexformatng = struct.Struct(">Qiiiiii20s12x")
220 versionformat = ">I" 220 indexformatng_pack = indexformatng.pack
221 versionformat = struct.Struct(">I")
222 versionformat_pack = versionformat.pack
223 versionformat_unpack = versionformat.unpack
221 224
222 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte 225 # corresponds to uncompressed length of indexformatng (2 gigs, 4-byte
223 # signed integer) 226 # signed integer)
224 _maxentrysize = 0x7fffffff 227 _maxentrysize = 0x7fffffff
225 228
226 class revlogio(object): 229 class revlogio(object):
227 def __init__(self): 230 def __init__(self):
228 self.size = struct.calcsize(indexformatng) 231 self.size = indexformatng.size
229 232
230 def parseindex(self, data, inline): 233 def parseindex(self, data, inline):
231 # call the C implementation to parse the index data 234 # call the C implementation to parse the index data
232 index, cache = parsers.parse_index2(data, inline) 235 index, cache = parsers.parse_index2(data, inline)
233 return index, getattr(index, 'nodemap', None), cache 236 return index, getattr(index, 'nodemap', None), cache
234 237
235 def packentry(self, entry, node, version, rev): 238 def packentry(self, entry, node, version, rev):
236 p = _pack(indexformatng, *entry) 239 p = indexformatng_pack(*entry)
237 if rev == 0: 240 if rev == 0:
238 p = _pack(versionformat, version) + p[4:] 241 p = versionformat_pack(version) + p[4:]
239 return p 242 return p
240 243
241 class revlog(object): 244 class revlog(object):
242 """ 245 """
243 the underlying revision storage object 246 the underlying revision storage object
333 try: 336 try:
334 f = self.opener(self.indexfile) 337 f = self.opener(self.indexfile)
335 indexdata = f.read() 338 indexdata = f.read()
336 f.close() 339 f.close()
337 if len(indexdata) > 0: 340 if len(indexdata) > 0:
338 v = struct.unpack(versionformat, indexdata[:4])[0] 341 v = versionformat_unpack(indexdata[:4])[0]
339 self._initempty = False 342 self._initempty = False
340 except IOError as inst: 343 except IOError as inst:
341 if inst.errno != errno.ENOENT: 344 if inst.errno != errno.ENOENT:
342 raise 345 raise
343 346