Skip to content

Commit a5e7c4e

Browse files
umaxbrian-brazil
authored andcommitted
Use precompiled struct methods for pack, unpack data (prometheus#266)
1 parent 569908a commit a5e7c4e

File tree

1 file changed

+22
-9
lines changed

1 file changed

+22
-9
lines changed

prometheus_client/core.py

Lines changed: 22 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@
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

3338
class 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

Comments
 (0)