Skip to content

Commit e0a6e64

Browse files
edma2jack-berg
andauthored
lazily initialize ReservoirCells (#6851)
Co-authored-by: jack-berg <[email protected]>
1 parent cde3d45 commit e0a6e64

File tree

1 file changed

+22
-6
lines changed

1 file changed

+22
-6
lines changed

sdk/metrics/src/main/java/io/opentelemetry/sdk/metrics/internal/exemplar/FixedSizeExemplarReservoir.java

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,16 @@
1313
import java.util.Collections;
1414
import java.util.List;
1515
import java.util.function.BiFunction;
16+
import javax.annotation.Nullable;
1617

1718
/** Base for fixed-size reservoir sampling of Exemplars. */
1819
abstract class FixedSizeExemplarReservoir<T extends ExemplarData> implements ExemplarReservoir<T> {
1920

20-
private final ReservoirCell[] storage;
21+
@Nullable private ReservoirCell[] storage;
2122
private final ReservoirCellSelector reservoirCellSelector;
2223
private final BiFunction<ReservoirCell, Attributes, T> mapAndResetCell;
24+
private final int size;
25+
private final Clock clock;
2326
private volatile boolean hasMeasurements = false;
2427

2528
/** Instantiates an exemplar reservoir of fixed size. */
@@ -28,16 +31,18 @@ abstract class FixedSizeExemplarReservoir<T extends ExemplarData> implements Exe
2831
int size,
2932
ReservoirCellSelector reservoirCellSelector,
3033
BiFunction<ReservoirCell, Attributes, T> mapAndResetCell) {
31-
this.storage = new ReservoirCell[size];
32-
for (int i = 0; i < size; ++i) {
33-
this.storage[i] = new ReservoirCell(clock);
34-
}
34+
this.storage = null; // lazily initialize to avoid allocations
35+
this.size = size;
36+
this.clock = clock;
3537
this.reservoirCellSelector = reservoirCellSelector;
3638
this.mapAndResetCell = mapAndResetCell;
3739
}
3840

3941
@Override
4042
public void offerLongMeasurement(long value, Attributes attributes, Context context) {
43+
if (storage == null) {
44+
storage = initStorage();
45+
}
4146
int bucket = reservoirCellSelector.reservoirCellIndexFor(storage, value, attributes, context);
4247
if (bucket != -1) {
4348
this.storage[bucket].recordLongMeasurement(value, attributes, context);
@@ -47,16 +52,27 @@ public void offerLongMeasurement(long value, Attributes attributes, Context cont
4752

4853
@Override
4954
public void offerDoubleMeasurement(double value, Attributes attributes, Context context) {
55+
if (storage == null) {
56+
storage = initStorage();
57+
}
5058
int bucket = reservoirCellSelector.reservoirCellIndexFor(storage, value, attributes, context);
5159
if (bucket != -1) {
5260
this.storage[bucket].recordDoubleMeasurement(value, attributes, context);
5361
this.hasMeasurements = true;
5462
}
5563
}
5664

65+
private ReservoirCell[] initStorage() {
66+
ReservoirCell[] storage = new ReservoirCell[this.size];
67+
for (int i = 0; i < size; ++i) {
68+
storage[i] = new ReservoirCell(this.clock);
69+
}
70+
return storage;
71+
}
72+
5773
@Override
5874
public List<T> collectAndReset(Attributes pointAttributes) {
59-
if (!hasMeasurements) {
75+
if (!hasMeasurements || storage == null) {
6076
return Collections.emptyList();
6177
}
6278
// Note: we are collecting exemplars from buckets piecemeal, but we

0 commit comments

Comments
 (0)