diff --git a/.changelog/5288.changed b/.changelog/5288.changed new file mode 100644 index 0000000000..224761ac36 --- /dev/null +++ b/.changelog/5288.changed @@ -0,0 +1 @@ +opentelemetry-api: remove unnecessary copy in iterator \ No newline at end of file diff --git a/opentelemetry-api/src/opentelemetry/attributes/__init__.py b/opentelemetry-api/src/opentelemetry/attributes/__init__.py index 58b2901a6b..4669468b8e 100644 --- a/opentelemetry-api/src/opentelemetry/attributes/__init__.py +++ b/opentelemetry-api/src/opentelemetry/attributes/__init__.py @@ -309,7 +309,7 @@ def __delitem__(self, key: str) -> None: def __iter__(self): # type: ignore with self._lock: - return iter(self._dict.copy()) # type: ignore + return iter(list(self._dict)) # type: ignore def __len__(self) -> int: return len(self._dict) diff --git a/opentelemetry-sdk/benchmarks/trace/test_benchmark_trace.py b/opentelemetry-sdk/benchmarks/trace/test_benchmark_trace.py index 7757dbab12..0e110514ba 100644 --- a/opentelemetry-sdk/benchmarks/trace/test_benchmark_trace.py +++ b/opentelemetry-sdk/benchmarks/trace/test_benchmark_trace.py @@ -1,10 +1,12 @@ # Copyright The OpenTelemetry Authors # SPDX-License-Identifier: Apache-2.0 +import tracemalloc from functools import lru_cache import pytest +from opentelemetry.attributes import BoundedAttributes from opentelemetry.sdk.resources import Resource from opentelemetry.sdk.trace import ( ReadableSpan, @@ -192,3 +194,24 @@ def benchmark_read_links(): span.end() benchmark(benchmark_read_links) + + +@pytest.mark.parametrize("num_attrs", [1, 10, 50, 128]) +def test_bounded_attribute_iterator(benchmark, num_attrs): + attrs = BoundedAttributes( + attributes={f"key{i}": f"value{i}" for i in range(num_attrs)} + ) + + peaks = [] + for _ in range(200): + tracemalloc.start() + list(attrs) + _, peak = tracemalloc.get_traced_memory() + tracemalloc.stop() + peaks.append(peak) + benchmark.extra_info["mean_alloc_bytes"] = sum(peaks) / len(peaks) + + def benchmark_iter(): + list(attrs) + + benchmark(benchmark_iter)