Skip to content

Commit de15a97

Browse files
committed
PR feedback
Signed-off-by: Jack Berg <[email protected]>
1 parent ad1e7cb commit de15a97

File tree

1 file changed

+13
-6
lines changed
  • prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics

1 file changed

+13
-6
lines changed

prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/Buffer.java

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,14 @@
1818
class Buffer {
1919

2020
private static final long bufferActiveBit = 1L << 63;
21+
// Tracking observation counts requires an AtomicLong for coordination between recording and
22+
// collecting. AtomicLong does much worse under contention than the LongAdder instances used
23+
// elsewhere to hold aggregated state. To improve, we stripe the AtomicLong into N instances,
24+
// where N is the number of available processors. Each record operation chooses the appropriate
25+
// instance to use based on the modulo of its thread id and N. This is a more naive / simple
26+
// implementation compared to the striping used under the hood in java.util.concurrent classes
27+
// like LongAdder - contention and hot spots can still occur if recording thread ids happen to
28+
// resolve to the same index. Further improvement is possible.
2129
private final AtomicLong[] stripedObservationCounts;
2230
private double[] observationBuffer = new double[0];
2331
private int bufferPos = 0;
@@ -35,9 +43,8 @@ class Buffer {
3543
}
3644

3745
boolean append(double value) {
38-
AtomicLong observationCountForThread =
39-
stripedObservationCounts[
40-
((int) Thread.currentThread().getId()) % stripedObservationCounts.length];
46+
int index = Math.abs((int) Thread.currentThread().getId()) % stripedObservationCounts.length;
47+
AtomicLong observationCountForThread = stripedObservationCounts[index];
4148
long count = observationCountForThread.incrementAndGet();
4249
if ((count & bufferActiveBit) == 0) {
4350
return false; // sign bit not set -> buffer not active.
@@ -79,7 +86,7 @@ <T extends DataPointSnapshot> T run(
7986
runLock.lock();
8087
try {
8188
// Signal that the buffer is active.
82-
Long expectedCount = 0L;
89+
long expectedCount = 0L;
8390
for (AtomicLong observationCount : stripedObservationCounts) {
8491
expectedCount += observationCount.getAndAdd(bufferActiveBit);
8592
}
@@ -97,12 +104,12 @@ <T extends DataPointSnapshot> T run(
97104
long expectedBufferSize = 0;
98105
if (reset) {
99106
for (AtomicLong observationCount : stripedObservationCounts) {
100-
expectedBufferSize += (int) (observationCount.getAndSet(0) & ~bufferActiveBit);
107+
expectedBufferSize += observationCount.getAndSet(0) & ~bufferActiveBit;
101108
}
102109
reset = false;
103110
} else {
104111
for (AtomicLong observationCount : stripedObservationCounts) {
105-
expectedBufferSize += (int) observationCount.addAndGet(bufferActiveBit);
112+
expectedBufferSize += observationCount.addAndGet(bufferActiveBit);
106113
}
107114
}
108115
expectedBufferSize -= expectedCount;

0 commit comments

Comments
 (0)