Skip to content

Commit 3f0f2a8

Browse files
committed
fix(serializer): avoid copying the whole Mapping before trimming to MAX_DATABAG_BREADTH
1 parent e2dd162 commit 3f0f2a8

1 file changed

Lines changed: 10 additions & 4 deletions

File tree

sentry_sdk/serializer.py

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
from array import array
44
from collections.abc import Mapping
55
from datetime import datetime
6+
from itertools import islice
67
from typing import TYPE_CHECKING
78

89
from sentry_sdk.utils import (
@@ -299,16 +300,21 @@ def _serialize_node_impl(
299300
)
300301

301302
elif isinstance(obj, Mapping):
302-
# Create temporary copy here to avoid calling too much code that
303-
# might mutate our dictionary while we're still iterating over it.
304-
obj = dict(obj.items())
303+
# Copy only as many pairs as we might keep - avoids O(len(obj)) work
304+
# when obj is huge (e.g. a large cache captured as a frame local),
305+
# while still protecting against mutation during iteration.
306+
obj_len = len(obj)
307+
if isinstance(remaining_breadth, int):
308+
obj = dict(islice(obj.items(), remaining_breadth + 1))
309+
else:
310+
obj = dict(obj.items())
305311

306312
rv_dict: "Dict[str, Any]" = {}
307313
i = 0
308314

309315
for k, v in obj.items():
310316
if remaining_breadth is not None and i >= remaining_breadth:
311-
self._annotate(len=len(obj))
317+
self._annotate(len=obj_len)
312318
break
313319

314320
str_k = str(k)

0 commit comments

Comments
 (0)