eval: Prometheus client profiling sweep + findings - #196
Closed
GnaneshGnani wants to merge 1 commit into
Closed
GnaneshGnani wants to merge 1 commit into
GnaneshGnani wants to merge 1 commit into
Conversation
GnaneshGnani
marked this pull request as ready for review
April 28, 2026 03:01
GnaneshGnani
force-pushed
the
eval/prometheus-client-profiling
branch
from
April 28, 2026 03:56
4a673b8 to
6cada86
Compare
GnaneshGnani
force-pushed
the
eval/prometheus-client-profiling
branch
from
May 1, 2026 03:50
6cada86 to
022cb39
Compare
GnaneshGnani
force-pushed
the
eval/prometheus-client-profiling
branch
from
May 1, 2026 03:52
022cb39 to
edd4602
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
First pass of producer-side Prometheus
client_golangprofiling, stacked on #195.This PR answers one narrow question:
The measured path is only:
The collector, gateway, backend, remote-write path, and sketch processors are intentionally outside the measurement. That makes this comparable to #195 in scope: both PRs measure source-side cost before downstream systems get involved.
Headline Result
At high cardinality and high update rate, the main cost is not scraping. It is per-event dynamic label lookup through
WithLabelValues.WithLabelValuesupdate-only,C=10000,F=1000combined,C=10000,F=1000,S=1scombined, same cell, scrape p95scrape-only,C=10000,S=1s, scrape p95Interpretation: cached Prometheus metric handles look viable for high-rate producers. Calling
WithLabelValueson every event becomes the dominant producer-side cost at high cardinality.What This Adds
Code and harness:
deploy/fake-exporter/EXPORTER_CLIENT=prometheus, Prometheus instruments,/metrics, and/debug/pprof/*deploy/scripts/run-prom-client-profile-cell.shdeploy/scripts/run-prom-client-profiling-eval.shdeploy/scripts/prom-client-cell-summary.pyChecked-in results under
deploy/eval-results/prom-client/mirror the artifact style in #195: findings, summary CSV, and top-level run log.FINDINGS-20260427.mdprom-client-profiling-20260427-151128.csvprom-client-profiling-20260427-151128.log.gitignoreGenerated locally but not checked in:
profiles/*.cpu.pb,profiles/*.heap.pbprofiles/*.top.txtgo tool pprof -topsummarieslogs/*How To Read The Experiment
The run has three phases because Prometheus client cost has two different sources: producer updates and scrape exposition.
update-onlyscrape-onlyEXPORTER_FREQ_HZ=0; scrape loop runs/metricscollection and text expositioncombined/metricsis scrapedThe two update modes model the most important Prometheus client usage choice:
cacheddynamicWithLabelValues(...)on every eventThe matrix was:
C1000,10000F10,100,1000HzS1s,15s,60scounter,gaugeSOAK_S=60,PROFILE_SECONDS=30histogramsupport is implemented in the exporter but not included in this first run. The first pass keepscounter,gaugeso the workload matches the #195 source-side signals; histogram profiling can be a follow-up if we want bucket update cost specifically.Result Tables
Update-only isolates producer metric updates:
Combined with 1-second scraping shows the realistic stress case:
Scrape-only with 1-second scraping isolates
/metricsexposition:Profile Findings
The local pprof summaries explain the CPU gap:
MetricVec.GetMetricWithLabelValues,MetricVec.hashLabelValues,metricMap.getMetricWithHashAndLabelValues, andsync/atomic.(*Int32).Add.Validation
go test ./...indeploy/fake-exporterbash -n deploy/scripts/run-prom-client-profile-cell.sh deploy/scripts/run-prom-client-profiling-eval.shpython3 -m py_compile deploy/scripts/prom-client-cell-summary.pygit diff --cached --checkbefore commitCaveats
N=1, so it is enough for a first-pass shape, not variance bars.docker stats --no-streamCPU values are point-in-time samples. The pprof files are the stronger source for hot functions, but they are kept local-only to avoid bloating the PR.Next
Use this pass as the Prometheus-client counterpart to #195. If we need paper-quality confidence intervals, rerun the same matrix multiple times. If we need Prometheus histogram-specific cost, rerun with
EXPORTER_PROM_INSTRUMENTS=counter,gauge,histogramas a separate follow-up so the bucket-update cost is not mixed into this first comparison.