Skip to content

Commit 8939ea3

Browse files
authored
PYTHON-4640 Improve performance of creating ObjectIds with multiple threads (mongodb#1781)
1 parent b14420a commit 8939ea3

File tree

1 file changed

+9
-12
lines changed

1 file changed

+9
-12
lines changed

bson/objectid.py

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@
2929
from bson.tz_util import utc
3030

3131
_MAX_COUNTER_VALUE = 0xFFFFFF
32+
_PACK_INT = struct.Struct(">I").pack
33+
_PACK_INT_RANDOM = struct.Struct(">I5s").pack
34+
_UNPACK_INT = struct.Struct(">I").unpack
3235

3336

3437
def _raise_invalid_id(oid: str) -> NoReturn:
@@ -132,7 +135,7 @@ def from_datetime(cls: Type[ObjectId], generation_time: datetime.datetime) -> Ob
132135
if offset is not None:
133136
generation_time = generation_time - offset
134137
timestamp = calendar.timegm(generation_time.timetuple())
135-
oid = struct.pack(">I", int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00"
138+
oid = _PACK_INT(int(timestamp)) + b"\x00\x00\x00\x00\x00\x00\x00\x00"
136139
return cls(oid)
137140

138141
@classmethod
@@ -163,18 +166,12 @@ def _random(cls) -> bytes:
163166

164167
def __generate(self) -> None:
165168
"""Generate a new value for this ObjectId."""
166-
# 4 bytes current time
167-
oid = struct.pack(">I", int(time.time()))
168-
169-
# 5 bytes random
170-
oid += ObjectId._random()
171-
172-
# 3 bytes inc
173169
with ObjectId._inc_lock:
174-
oid += struct.pack(">I", ObjectId._inc)[1:4]
175-
ObjectId._inc = (ObjectId._inc + 1) % (_MAX_COUNTER_VALUE + 1)
170+
inc = ObjectId._inc
171+
ObjectId._inc = (inc + 1) % (_MAX_COUNTER_VALUE + 1)
176172

177-
self.__id = oid
173+
# 4 bytes current time, 5 bytes random, 3 bytes inc.
174+
self.__id = _PACK_INT_RANDOM(int(time.time()), ObjectId._random()) + _PACK_INT(inc)[1:4]
178175

179176
def __validate(self, oid: Any) -> None:
180177
"""Validate and use the given id for this ObjectId.
@@ -212,7 +209,7 @@ def generation_time(self) -> datetime.datetime:
212209
represents the generation time in UTC. It is precise to the
213210
second.
214211
"""
215-
timestamp = struct.unpack(">I", self.__id[0:4])[0]
212+
timestamp = _UNPACK_INT(self.__id[0:4])[0]
216213
return datetime.datetime.fromtimestamp(timestamp, utc)
217214

218215
def __getstate__(self) -> bytes:

0 commit comments

Comments
 (0)