Skip to content

Commit d1e8b34

Browse files
Heldroebrian-brazil
authored andcommitted
Multiprocess mode: using direct assignment for writing into mmap (prometheus#315)
Using pack_into can create atomicity problems when writing on cpython, setting the bytes to 0 before writing the value. When having a lot of writes, some reads would return 0 instead of the real value. Signed-off-by: David Guerrero <heldroe@gmail.com>
1 parent c0cee96 commit d1e8b34

File tree

1 file changed

+13
-2
lines changed

1 file changed

+13
-2
lines changed

prometheus_client/core.py

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
_MINUS_INF = float("-inf")
3131
_INITIAL_MMAP_SIZE = 1 << 20
3232

33-
_pack_integer = struct.Struct(b'i').pack_into
34-
_pack_double = struct.Struct(b'd').pack_into
33+
_pack_integer_func = struct.Struct(b'i').pack
34+
_pack_double_func = struct.Struct(b'd').pack
3535
_unpack_integer = struct.Struct(b'i').unpack_from
3636
_unpack_double = struct.Struct(b'd').unpack_from
3737

@@ -493,6 +493,17 @@ def get(self):
493493
return self._value
494494

495495

496+
# struct.pack_into has atomicity issues because it will temporarily write 0 into
497+
# the mmap, resulting in false reads to 0 when experiencing a lot of writes.
498+
# Using direct assignment solves this issue.
499+
def _pack_double(data, pos, value):
500+
data[pos:pos + 8] = _pack_double_func(value)
501+
502+
503+
def _pack_integer(data, pos, value):
504+
data[pos:pos + 4] = _pack_integer_func(value)
505+
506+
496507
class _MmapedDict(object):
497508
"""A dict of doubles, backed by an mmapped file.
498509

0 commit comments

Comments
 (0)