2929_MINUS_INF = float ("-inf" )
3030_INITIAL_MMAP_SIZE = 1 << 20
3131
32+ _pack_integer = struct .Struct (b'i' ).pack_into
33+ _pack_double = struct .Struct (b'd' ).pack_into
34+ _unpack_integer = struct .Struct (b'i' ).unpack_from
35+ _unpack_double = struct .Struct (b'd' ).unpack_from
36+
3237
3338class CollectorRegistry (object ):
3439 '''Metric collector registry.
@@ -353,10 +358,10 @@ def __init__(self, filename, read_mode=False):
353358 self ._m = mmap .mmap (self ._f .fileno (), self ._capacity )
354359
355360 self ._positions = {}
356- self ._used = struct . unpack_from ( b'i' , self ._m , 0 )[0 ]
361+ self ._used = _unpack_integer ( self ._m , 0 )[0 ]
357362 if self ._used == 0 :
358363 self ._used = 8
359- struct . pack_into ( b'i' , self ._m , 0 , self ._used )
364+ _pack_integer ( self ._m , 0 , self ._used )
360365 else :
361366 if not read_mode :
362367 for key , _ , pos in self ._read_all_values ():
@@ -376,19 +381,27 @@ def _init_value(self, key):
376381
377382 # Update how much space we've used.
378383 self ._used += len (value )
379- struct . pack_into ( b'i' , self ._m , 0 , self ._used )
384+ _pack_integer ( self ._m , 0 , self ._used )
380385 self ._positions [key ] = self ._used - 8
381386
382387 def _read_all_values (self ):
383388 """Yield (key, value, pos). No locking is performed."""
389+
384390 pos = 8
385- while pos < self ._used :
386- encoded_len = struct .unpack_from (b'i' , self ._m , pos )[0 ]
391+
392+ # cache variables to local ones and prevent attributes lookup
393+ # on every loop iteration
394+ used = self ._used
395+ data = self ._m
396+ unpack_from = struct .unpack_from
397+
398+ while pos < used :
399+ encoded_len = _unpack_integer (data , pos )[0 ]
387400 pos += 4
388- encoded = struct . unpack_from ('{0}s' . format ( encoded_len ).encode (), self . _m , pos )[0 ]
401+ encoded = unpack_from (( '%ss' % encoded_len ).encode (), data , pos )[0 ]
389402 padded_len = encoded_len + (8 - (encoded_len + 4 ) % 8 )
390403 pos += padded_len
391- value = struct . unpack_from ( b'd' , self . _m , pos )[0 ]
404+ value = _unpack_double ( data , pos )[0 ]
392405 yield encoded .decode ('utf-8' ), value , pos
393406 pos += 8
394407
@@ -402,14 +415,14 @@ def read_value(self, key):
402415 self ._init_value (key )
403416 pos = self ._positions [key ]
404417 # We assume that reading from an 8 byte aligned value is atomic
405- return struct . unpack_from ( b'd' , self ._m , pos )[0 ]
418+ return _unpack_double ( self ._m , pos )[0 ]
406419
407420 def write_value (self , key , value ):
408421 if key not in self ._positions :
409422 self ._init_value (key )
410423 pos = self ._positions [key ]
411424 # We assume that writing to an 8 byte aligned value is atomic
412- struct . pack_into ( b'd' , self ._m , pos , value )
425+ _pack_double ( self ._m , pos , value )
413426
414427 def close (self ):
415428 if self ._f :
0 commit comments