Skip to content

perf: skip snapshot rebuild in mergeDuplicates when names are unique - #2441

Open
david-mollitor-db wants to merge 1 commit into
prometheus:mainfrom
david-mollitor-db:merge-duplicates-fast-path
Open

perf: skip snapshot rebuild in mergeDuplicates when names are unique#2441
david-mollitor-db wants to merge 1 commit into
prometheus:mainfrom
david-mollitor-db:merge-duplicates-fast-path

Conversation

@david-mollitor-db

Copy link
Copy Markdown

What

TextFormatUtil.mergeDuplicates currently only short-circuits when there is a single snapshot. For every scrape with two or more metric families it unconditionally builds a LinkedHashMap, an ArrayList per group, a MetricSnapshots.Builder (with its own list + set) and a freshly sorted MetricSnapshots — even when there is nothing to merge, which is the common case.

Since MetricSnapshots is always sorted by prometheus name (see its constructor), any duplicate names are adjacent. This adds a single allocation-free pass to detect duplicates; when there are none, the input is returned unchanged.

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;
}

The merge path for actual duplicates is unchanged.

Why

It removes the map / per-group list / builder / re-sort allocations on every scrape that has no duplicate metric names. Measured on a JMH benchmark of a histogram-heavy scrape (collect + serialize to the Prometheus text format), allocation on the serialize path dropped by ~880 B/op, scaling with the number of metric families.

Correctness

Output is byte-identical. The existing exposition-format tests pass, including DuplicateNamesExpositionTest, which exercises the merge path with real duplicate names.

This pull request and its description were written by Isaac.

MetricSnapshots is always sorted by prometheus name, so duplicate names are
adjacent. Detect duplicates in a single allocation-free pass and, when there
are none (the common case), return the input unchanged instead of rebuilding
it through a LinkedHashMap, an ArrayList per group, a MetricSnapshots.Builder
and a freshly sorted MetricSnapshots.

The merge path for actual duplicates is unchanged. Output is byte-identical
(verified by the existing exposition-format tests, including
DuplicateNamesExpositionTest).

Signed-off-by: David Mollitor <david.mollitor@databricks.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant