diff --git a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java index 6ad26fda3..140a5fc62 100644 --- a/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java +++ b/prometheus-metrics-core/src/main/java/io/prometheus/metrics/core/metrics/StatefulMetric.java @@ -116,20 +116,20 @@ public D labelValues(String... labelValues) { "Expected " + labelNames.length + " label values, but got " + labelValues.length + "."); } } - return data.computeIfAbsent( - Arrays.asList(labelValues), - l -> { - for (int i = 0; i < l.size(); i++) { - if (l.get(i) == null) { - throw new IllegalArgumentException( - "null label value for metric " - + metadata.getName() - + " and label " - + labelNames[i]); - } - } - return newDataPoint(); - }); + List key = Arrays.asList(labelValues); + // Fast path: the data point for these label values almost always already exists, since the same + // label combinations are reused across updates. + T dataPoint = data.get(key); + if (dataPoint != null) { + return dataPoint; + } + for (int i = 0; i < labelValues.length; i++) { + if (labelValues[i] == null) { + throw new IllegalArgumentException( + "null label value for metric " + metadata.getName() + " and label " + labelNames[i]); + } + } + return data.computeIfAbsent(key, l -> newDataPoint()); } /**