diff --git a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java index 8cfed2b29..9ca373e9f 100644 --- a/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java +++ b/prometheus-metrics-exposition-textformats/src/main/java/io/prometheus/metrics/expositionformats/TextFormatUtil.java @@ -41,6 +41,24 @@ public static MetricSnapshots mergeDuplicates(MetricSnapshots metricSnapshots) { return metricSnapshots; } + // MetricSnapshots is sorted by prometheus name, so any duplicates are adjacent. Detect them in + // a single allocation-free pass; when there are none (the common case) return the input as-is + // rather than rebuilding it through a map, a list per group and a new MetricSnapshots. + boolean hasDuplicates = false; + for (int i = 1; i < metricSnapshots.size(); i++) { + if (metricSnapshots + .get(i) + .getMetadata() + .getPrometheusName() + .equals(metricSnapshots.get(i - 1).getMetadata().getPrometheusName())) { + hasDuplicates = true; + break; + } + } + if (!hasDuplicates) { + return metricSnapshots; + } + Map> grouped = new LinkedHashMap<>(); for (MetricSnapshot snapshot : metricSnapshots) {