Skip to content

optimize hot path by caching contexual attribute - #4690

Merged
jgao54 merged 2 commits into
mainfrom
fix-ctx-optimization
Aug 13, 2026
Merged

optimize hot path by caching contexual attribute#4690
jgao54 merged 2 commits into
mainfrom
fix-ctx-optimization

Conversation

@jgao54

@jgao54 jgao54 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Two related fixes in this PR

1. Cache contextual attribute

All our counters/gauges are implemented with ContextAware*, which when executing Record will attempt to build attributes based on context:

func (a *ContextAwareInt64SyncGauge) Record(ctx context.Context, value int64, options ...metric.RecordOption) {
	newOptions := append([]metric.RecordOption{buildContextualAttributes(ctx)}, options...)
	a.Int64Gauge.Record(ctx, value, newOptions...)
}

This is intentional to standardize attributes (see buildContextualAttributes). However, on hot path like in the PullRecord loop, this can get pretty expensive and wasteful. We have observed flow-worker spending ~14% CPU just rebuilding attributes from the same context and generating the same result:

Screenshot 2026-08-12 at 19 03 38@2x

Fix here is to front the context building with a cache. Benchmark result on my machine shows ~3.6x improvement:

BenchmarkContextAwareGaugeRecord
BenchmarkContextAwareGaugeRecord/cache-hit
BenchmarkContextAwareGaugeRecord/cache-hit-14         	 2929458	       405.3 ns/op
BenchmarkContextAwareGaugeRecord/cache-miss
BenchmarkContextAwareGaugeRecord/cache-miss-14        	  781149	      1489 ns/op

2. Reduce gauge record frequency for MongoDB

A second optimization is in the MongoDB PullRecord loop, where instead of recording the gauge on every change event, only do so once per second. This is because SyncGauge is still not free (as seen in benchmark above), and Record just updates the cached value in the Gauge, not actually exporting it, so is essentially wasted work. This was attributing to another 5% of the cpu:

Screenshot 2026-08-12 at 19 04 55@2x

As a follow-up, worth also apply this change for PG/MySQL, but Mongo tends to be the most bottlenecked on CDC due to slow JSON processing, so prioritizing it here (also considered generalizing this mechanism into the gauge itself, but it's a bit unconventional to build sampling into gauge (more reasonable for traces).

@jgao54
jgao54 requested a review from a team as a code owner August 13, 2026 05:38
@claude

claude Bot commented Aug 13, 2026

Copy link
Copy Markdown

Code review

No issues found. Checked for bugs and CLAUDE.md compliance.

@dtunikov dtunikov left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

very nice

@jgao54
jgao54 force-pushed the fix-ctx-optimization branch from aa619f5 to bd9603c Compare August 13, 2026 09:58
@jgao54
jgao54 force-pushed the fix-ctx-optimization branch from bd9603c to fc4b5a2 Compare August 13, 2026 10:03
@jgao54

jgao54 commented Aug 13, 2026

Copy link
Copy Markdown
Contributor Author

Claude caught the scenario that when there are more than one mirrors in the flow pulling records concurrently, gauge will record in an interleaving manner with different context (since gauge/counter are singletons), and the cache wouldn't help much. Updated PR to have one cached entry per mirror instead. Benchmark shows the result before and after:

Before:

BenchmarkContextAwareGaugeRecord
BenchmarkContextAwareGaugeRecord/cache-hit
BenchmarkContextAwareGaugeRecord/cache-hit-14         	 2871757	       404.3 ns/op
BenchmarkContextAwareGaugeRecord/cache-miss
BenchmarkContextAwareGaugeRecord/cache-miss-14        	  790094	      1488 ns/op
BenchmarkContextAwareGaugeRecord/cache-hit-interleaved-ctx
BenchmarkContextAwareGaugeRecord/cache-hit-interleaved-ctx-14         	  796032	      1465 ns/op

After:

BenchmarkContextAwareGaugeRecord
BenchmarkContextAwareGaugeRecord/cache-hit
BenchmarkContextAwareGaugeRecord/cache-hit-14         	 2719821	       424.3 ns/op
BenchmarkContextAwareGaugeRecord/cache-miss
BenchmarkContextAwareGaugeRecord/cache-miss-14        	  751904	      1596 ns/op
BenchmarkContextAwareGaugeRecord/cache-hit-interleaved-ctx
BenchmarkContextAwareGaugeRecord/cache-hit-interleaved-ctx-14         	 2823506	       426.7 ns/op

@jgao54
jgao54 force-pushed the fix-ctx-optimization branch from fc4b5a2 to e906058 Compare August 13, 2026 10:15
@jgao54
jgao54 merged commit 25de5d2 into main Aug 13, 2026
21 checks passed
@jgao54
jgao54 deleted the fix-ctx-optimization branch August 13, 2026 17:17
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.

2 participants