From 3f0f2a8264da4d91e4f1b2a2ad515a596c51149d Mon Sep 17 00:00:00 2001 From: Dmitry Agafonov Date: Wed, 8 Jul 2026 15:11:32 +0300 Subject: [PATCH] fix(serializer): avoid copying the whole Mapping before trimming to MAX_DATABAG_BREADTH --- sentry_sdk/serializer.py | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/sentry_sdk/serializer.py b/sentry_sdk/serializer.py index 6bf6f6e70b..cba1319b6f 100644 --- a/sentry_sdk/serializer.py +++ b/sentry_sdk/serializer.py @@ -3,6 +3,7 @@ from array import array from collections.abc import Mapping from datetime import datetime +from itertools import islice from typing import TYPE_CHECKING from sentry_sdk.utils import ( @@ -299,16 +300,21 @@ def _serialize_node_impl( ) elif isinstance(obj, Mapping): - # Create temporary copy here to avoid calling too much code that - # might mutate our dictionary while we're still iterating over it. - obj = dict(obj.items()) + # Copy only as many pairs as we might keep - avoids O(len(obj)) work + # when obj is huge (e.g. a large cache captured as a frame local), + # while still protecting against mutation during iteration. + obj_len = len(obj) + if isinstance(remaining_breadth, int): + obj = dict(islice(obj.items(), remaining_breadth + 1)) + else: + obj = dict(obj.items()) rv_dict: "Dict[str, Any]" = {} i = 0 for k, v in obj.items(): if remaining_breadth is not None and i >= remaining_breadth: - self._annotate(len=len(obj)) + self._annotate(len=obj_len) break str_k = str(k)