Skip to content

Commit 9752faa

Browse files
committed
opentelemetry-sdk: speed up exemplars a bit
Use a sparse dict to allocate ExemplarsBucket on demand instead of preallocating all of them in FixedSizeExemplarReservoirABC. Make the following return around 2X more loops for both trace_based and always_off exemplars filter: .tox/benchmark-opentelemetry-sdk/bin/pytest opentelemetry-sdk/benchmarks/metrics/ -k 'test_histogram_record_1000[7]'
1 parent 37e422b commit 9752faa

File tree

1 file changed

+23
-12
lines changed

1 file changed

+23
-12
lines changed

opentelemetry-sdk/src/opentelemetry/sdk/metrics/_internal/exemplar/exemplar_reservoir.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,18 @@
1313
# limitations under the License.
1414

1515
from abc import ABC, abstractmethod
16+
from collections import defaultdict
1617
from random import randrange
17-
from typing import Any, Callable, Dict, List, Optional, Sequence, Union
18+
from typing import (
19+
Any,
20+
Callable,
21+
Dict,
22+
List,
23+
Mapping,
24+
Optional,
25+
Sequence,
26+
Union,
27+
)
1828

1929
from opentelemetry import trace
2030
from opentelemetry.context import Context
@@ -155,9 +165,9 @@ class FixedSizeExemplarReservoirABC(ExemplarReservoir):
155165
def __init__(self, size: int, **kwargs) -> None:
156166
super().__init__(**kwargs)
157167
self._size: int = size
158-
self._reservoir_storage: List[ExemplarBucket] = [
159-
ExemplarBucket() for _ in range(self._size)
160-
]
168+
self._reservoir_storage: Mapping[int, ExemplarBucket] = defaultdict(
169+
ExemplarBucket
170+
)
161171

162172
def collect(self, point_attributes: Attributes) -> List[Exemplar]:
163173
"""Returns accumulated Exemplars and also resets the reservoir for the next
@@ -171,15 +181,16 @@ def collect(self, point_attributes: Attributes) -> List[Exemplar]:
171181
exemplars contain the attributes that were filtered out by the aggregator,
172182
but recorded alongside the original measurement.
173183
"""
174-
exemplars = filter(
175-
lambda e: e is not None,
176-
map(
177-
lambda bucket: bucket.collect(point_attributes),
178-
self._reservoir_storage,
179-
),
180-
)
184+
exemplars = [
185+
e
186+
for e in (
187+
bucket.collect(point_attributes)
188+
for _, bucket in sorted(self._reservoir_storage.items())
189+
)
190+
if e is not None
191+
]
181192
self._reset()
182-
return [*exemplars]
193+
return exemplars
183194

184195
def offer(
185196
self,

0 commit comments

Comments
 (0)