From 7a00ccfcc7128b4e98437bba649a39b067f42305 Mon Sep 17 00:00:00 2001 From: Adam Johnson Date: Thu, 18 Dec 2025 00:23:00 +0000 Subject: [PATCH] Optimize `ObjectId.__str__()` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Like #2656, I spotted this function taking ~0.9% of request time in a project using mongoengine. [`bytes.hex()`](https://docs.python.org/3/library/stdtypes.html#bytes.hex) was added in Python 3.5 and does the same as `binascii.hexlify(...).decode()` but faster, so I've replaced it here. (The `binascii.hexlify()` docs also now point to `bytes.hex()` as a faster alternative.) Benchmarked again using [`richbench`](https://github.com/tonybaloney/rich-bench) with the below script.
bench_objectid_str.py ```python from __future__ import annotations import binascii import os class ObjectIdBefore: __slots__ = ("__id",) def __init__(self) -> None: self.__id = os.urandom(12) def __str__(self) -> str: return binascii.hexlify(self.__id).decode() class ObjectIdAfter: __slots__ = ("__id",) def __init__(self) -> None: self.__id = os.urandom(12) def __str__(self) -> str: return self.__id.hex() test_oids_before = [ObjectIdBefore() for _ in range(100)] test_oids_after = [ObjectIdAfter() for _ in range(100)] def bench_str_before(): for oid in test_oids_before: for _ in range(100_000): str(oid) def bench_str_after(): for oid in test_oids_after: for _ in range(100_000): str(oid) __benchmarks__ = [ (bench_str_before, bench_str_after, "str(ObjectId) - hex conversion"), ] ```
Results show a ~1.4x speedup: ``` $ uvx -p 3.13 richbench . Benchmarks, repeat=5, number=5 ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━┓ ┃ Benchmark ┃ Min ┃ Max ┃ Mean ┃ Min (+) ┃ Max (+) ┃ Mean (+) ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━┩ │ str(ObjectId) - hex conversion │ 3.000 │ 3.061 │ 3.019 │ 2.169 (1.4x) │ 2.231 (1.4x) │ 2.196 (1.4x) │ └────────────────────────────────┴─────────┴─────────┴─────────┴─────────────────┴─────────────────┴─────────────────┘ ``` --- bson/objectid.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/bson/objectid.py b/bson/objectid.py index 970c4e52e8..d3c64ef7c3 100644 --- a/bson/objectid.py +++ b/bson/objectid.py @@ -15,7 +15,6 @@ """Tools for working with MongoDB ObjectIds.""" from __future__ import annotations -import binascii import datetime import os import struct @@ -234,7 +233,7 @@ def __setstate__(self, value: Any) -> None: self.__id = oid def __str__(self) -> str: - return binascii.hexlify(self.__id).decode() + return self.__id.hex() def __repr__(self) -> str: return f"ObjectId('{self!s}')"