Commit 86533fd
authored
Improve histogram, summary performance under contention by striping observationCount (#1794)
Was working on improving the performance of opentelemetry-java metrics
under high contention, and realized that the same strategy I identified
to help over there helps for the prometheus implementation as well!
The idea here is recognizing that `Buffer.observationCount` is the
bottleneck under contention. In contrast to the other histogram /
summary `LongAdder` fields, `Buffer.observationCount` is `AtomicLong`
which performs much worse than `LongAdder` under high contention. Its
necessary that the type is `AtomicLong` because the CAS APIs accommodate
the two way communication that the record / collect paths need to signal
that a collection has started and all records have successfully
completed (preventing partial writes).
However, we can "have our cake and eat it to" by striping
`Buffer.observationCount` into many instances, such that the contention
on any instance is reduced. This is actually what `LongAdder` does under
the covers. This implementation stripes it into
`Runtime.getRuntime().availableProcessors()` instances, and uses
`Thread.currentThread().getId()) % stripedObservationCounts.length` to
select which instance any particular record thread should use.
Performance increase is substantial. Here's the before and after of
`HistogramBenchmark` on my machine (Apple M4 Mac Pro w/ 48gb RAM):
Before:
```
Benchmark Mode Cnt Score Error Units
HistogramBenchmark.openTelemetryClassic thrpt 25 1138.465 ± 165.921 ops/s
HistogramBenchmark.openTelemetryExponential thrpt 25 677.483 ± 28.765 ops/s
HistogramBenchmark.prometheusClassic thrpt 25 5126.048 ± 153.878 ops/s
HistogramBenchmark.prometheusNative thrpt 25 3854.323 ± 107.789 ops/s
HistogramBenchmark.simpleclient thrpt 25 13285.351 ± 1784.506 ops/s
```
After:
```
Benchmark Mode Cnt Score Error Units
HistogramBenchmark.openTelemetryClassic thrpt 25 925.528 ± 13.744 ops/s
HistogramBenchmark.openTelemetryExponential thrpt 25 584.404 ± 32.762 ops/s
HistogramBenchmark.prometheusClassic thrpt 25 14623.971 ± 2117.588 ops/s
HistogramBenchmark.prometheusNative thrpt 25 7405.672 ± 857.611 ops/s
HistogramBenchmark.simpleclient thrpt 25 13102.822 ± 3081.096 ops/s
```
---------
Signed-off-by: Jack Berg <34418638+jack-berg@users.noreply.github.com>1 parent e07e6dd commit 86533fd
File tree
1 file changed
+31
-7
lines changed- prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics
1 file changed
+31
-7
lines changedLines changed: 31 additions & 7 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
18 | 18 | | |
19 | 19 | | |
20 | 20 | | |
21 | | - | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
22 | 30 | | |
23 | 31 | | |
24 | 32 | | |
| |||
27 | 35 | | |
28 | 36 | | |
29 | 37 | | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
| 44 | + | |
30 | 45 | | |
31 | | - | |
| 46 | + | |
| 47 | + | |
| 48 | + | |
32 | 49 | | |
33 | 50 | | |
34 | 51 | | |
| |||
69 | 86 | | |
70 | 87 | | |
71 | 88 | | |
72 | | - | |
| 89 | + | |
| 90 | + | |
| 91 | + | |
| 92 | + | |
73 | 93 | | |
74 | 94 | | |
75 | 95 | | |
| |||
81 | 101 | | |
82 | 102 | | |
83 | 103 | | |
84 | | - | |
| 104 | + | |
85 | 105 | | |
86 | | - | |
87 | | - | |
| 106 | + | |
| 107 | + | |
| 108 | + | |
88 | 109 | | |
89 | 110 | | |
90 | | - | |
| 111 | + | |
| 112 | + | |
| 113 | + | |
91 | 114 | | |
| 115 | + | |
92 | 116 | | |
93 | 117 | | |
94 | 118 | | |
| |||
0 commit comments