Skip to content

Commit cdc5043

Browse files
amurarufstab
authored andcommitted
Improve performance of duplicate sample lookup
Maintain a lookup index for sample keys (name, labels) and use that to check for duplicate sample during scraping instead of O(n) list of samples Also guard non-trivial computation behind Logger level check Signed-off-by: Adi Muraru <amuraru@adobe.com>
1 parent 3bdc716 commit cdc5043

File tree

1 file changed

+53
-6
lines changed

1 file changed

+53
-6
lines changed

collector/src/main/java/io/prometheus/jmx/JmxCollector.java

Lines changed: 53 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,15 @@
1414
import java.io.StringWriter;
1515
import java.util.ArrayList;
1616
import java.util.HashMap;
17+
import java.util.HashSet;
1718
import java.util.Iterator;
1819
import java.util.LinkedHashMap;
1920
import java.util.LinkedList;
2021
import java.util.List;
2122
import java.util.Map;
2223
import java.util.Set;
2324
import java.util.TreeMap;
25+
import java.util.logging.Level;
2426
import java.util.logging.Logger;
2527
import java.util.regex.Matcher;
2628
import java.util.regex.Pattern;
@@ -335,9 +337,50 @@ private static boolean isLegalCharacter(char input) {
335337
(input >= '0' && input <= '9'));
336338
}
337339

338-
class Receiver implements JmxScraper.MBeanReceiver {
340+
/**
341+
* A sample is uniquely identified by its name, labelNames and labelValues
342+
*/
343+
static class SampleKey {
344+
String name;
345+
List<String> labelNames;
346+
List<String> labelValues;
347+
348+
SampleKey(String name, List<String> labelNames, List<String> labelValues) {
349+
this.name = name;
350+
this.labelNames = labelNames;
351+
this.labelValues = labelValues;
352+
}
353+
354+
static SampleKey of(MetricFamilySamples.Sample sample) {
355+
return new SampleKey(sample.name, sample.labelNames, sample.labelValues);
356+
}
357+
358+
@Override
359+
public boolean equals(Object o) {
360+
if (this == o) return true;
361+
if (o == null || getClass() != o.getClass()) return false;
362+
363+
SampleKey sampleKey = (SampleKey) o;
364+
365+
if (name != null ? !name.equals(sampleKey.name) : sampleKey.name != null) return false;
366+
if (labelNames != null ? !labelNames.equals(sampleKey.labelNames) : sampleKey.labelNames != null) return false;
367+
return labelValues != null ? labelValues.equals(sampleKey.labelValues) : sampleKey.labelValues == null;
368+
}
369+
370+
@Override
371+
public int hashCode() {
372+
int result = name != null ? name.hashCode() : 0;
373+
result = 31 * result + (labelNames != null ? labelNames.hashCode() : 0);
374+
result = 31 * result + (labelValues != null ? labelValues.hashCode() : 0);
375+
return result;
376+
}
377+
378+
}
379+
380+
static class Receiver implements JmxScraper.MBeanReceiver {
339381
Map<String, MetricFamilySamples> metricFamilySamplesMap =
340382
new HashMap<String, MetricFamilySamples>();
383+
Set<SampleKey> uniqueSampleKeys = new HashSet<SampleKey>();
341384

342385
Config config;
343386
MatchedRulesCache.StalenessTracker stalenessTracker;
@@ -362,16 +405,20 @@ void addSample(MetricFamilySamples.Sample sample, Type type, String help) {
362405
mfs = new MetricFamilySamples(sample.name, type, help, new ArrayList<MetricFamilySamples.Sample>());
363406
metricFamilySamplesMap.put(sample.name, mfs);
364407
}
365-
MetricFamilySamples.Sample existing = findExisting(sample, mfs);
366-
if (existing != null) {
408+
SampleKey sampleKey = SampleKey.of(sample);
409+
boolean exists = uniqueSampleKeys.contains(sampleKey);
410+
if (exists) {
411+
if (LOGGER.isLoggable(Level.FINE)) {
367412
String labels = "{";
368-
for (int i=0; i<existing.labelNames.size(); i++) {
369-
labels += existing.labelNames.get(i) + "=" + existing.labelValues.get(i) + ",";
413+
for (int i = 0; i < sample.labelNames.size(); i++) {
414+
labels += sample.labelNames.get(i) + "=" + sample.labelValues.get(i) + ",";
370415
}
371416
labels += "}";
372-
LOGGER.fine("Metric " + existing.name + labels + " was created multiple times. Keeping the first occurrence. Dropping the others.");
417+
LOGGER.fine("Metric " + sample.name + labels + " was created multiple times. Keeping the first occurrence. Dropping the others.");
418+
}
373419
} else {
374420
mfs.samples.add(sample);
421+
uniqueSampleKeys.add(sampleKey);
375422
}
376423
}
377424

0 commit comments

Comments
 (0)