Skip to content

Optimize Tag Handling in DefaultMeterObservationHandler #6035

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

HYEONSEOK1
Copy link
Contributor

Optimize Tag Handling in DefaultMeterObservationHandler

Summary

This PR optimizes tag handling in DefaultMeterObservationHandler by introducing a caching mechanism using ConcurrentHashMap.
It addresses micrometer-metrics/micrometer#6031, which reports performance degradation due to unnecessary tag sorting.

Changes Introduced

🔹 Tag Caching Mechanism

  • Added ConcurrentHashMap<Map.Entry<String, KeyValues>, Tags> to cache computed Tags instances.
  • Prevents redundant sorting and allocation of tag lists on each method invocation.

🔹 Optimized getOrCreateTags Method

  • Retrieves precomputed Tags from the cache when available.
  • Computes and caches Tags only if not already stored.

🔹 Ensured Ordering with KeyValues

  • KeyValues is a SortedSet, maintaining natural ordering.
  • Guarantees consistent tag order without additional sorting overhead.

Let me know if any refinements are needed! 🚀

@HYEONSEOK1 HYEONSEOK1 force-pushed the cache-tags branch 3 times, most recently from fe276cf to 429f5c6 Compare March 17, 2025 15:32
@shakuzen
Copy link
Member

Thanks for the pull request. I'll take a closer look later, but having JMH benchmarks would help quantify and demonstrate the difference this makes.

@HYEONSEOK1
Copy link
Contributor Author

HYEONSEOK1 commented Mar 21, 2025

@shakuzen
Thanks for the feedback!

I've added JMH benchmarks to quantify the performance difference before and after the optimizations. Below is a comparison of the results:

Benchmark Results

Click to view benchmark results Threads(4)

Benchmark Results

Baseline

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.baseline sample 1534516 0.068 ± 0.001 us/op
ObservationBenchmark.baseline:p0.00 sample ≈ 0 us/op
ObservationBenchmark.baseline:p0.50 sample 0.042 us/op
ObservationBenchmark.baseline:p0.90 sample 0.125 us/op
ObservationBenchmark.baseline:p0.95 sample 0.209 us/op
ObservationBenchmark.baseline:p0.99 sample 0.417 us/op
ObservationBenchmark.baseline:p0.999 sample 0.959 us/op
ObservationBenchmark.baseline:p0.9999 sample 3.854 us/op
ObservationBenchmark.baseline:p1.00 sample 19.552 us/op

Observation

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observation sample 977538 1.347 ± 0.014 us/op
ObservationBenchmark.observation:p0.00 sample 0.500 us/op
ObservationBenchmark.observation:p0.50 sample 1.084 us/op
ObservationBenchmark.observation:p0.90 sample 2.042 us/op
ObservationBenchmark.observation:p0.95 sample 2.372 us/op
ObservationBenchmark.observation:p0.99 sample 3.000 us/op
ObservationBenchmark.observation:p0.999 sample 5.832 us/op
ObservationBenchmark.observation:p0.9999 sample 32.040 us/op
ObservationBenchmark.observation:p1.00 sample 584.704 us/op

Observation With optimisations (40f6268)

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observation2 sample 1094942 1.207 ± 0.012 us/op
ObservationBenchmark.observation2:p0.00 sample 0.333 us/op
ObservationBenchmark.observation2:p0.50 sample 0.959 us/op
ObservationBenchmark.observation2:p0.90 sample 1.874 us/op
ObservationBenchmark.observation2:p0.95 sample 2.208 us/op
ObservationBenchmark.observation2:p0.99 sample 2.832 us/op
ObservationBenchmark.observation2:p0.999 sample 3.956 us/op
ObservationBenchmark.observation2:p0.9999 sample 21.923 us/op
ObservationBenchmark.observation2:p1.00 sample 559.104 us/op

Observation Without Thread Contention

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observationWithoutThreadContention sample 267386 0.323 ± 0.021 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.00 sample 0.208 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.50 sample 0.292 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.90 sample 0.333 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.95 sample 0.334 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.99 sample 0.417 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.999 sample 1.374 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.9999 sample 13.557 us/op
ObservationBenchmark.observationWithoutThreadContention:p1.00 sample 718.848 us/op

Observation Without Thread Contention With optimisations (40f6268)

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observationWithoutThreadContention2 sample 288505 0.303 ± 0.017 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.00 sample 0.167 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.50 sample 0.291 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.90 sample 0.333 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.95 sample 0.334 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.99 sample 0.417 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.999 sample 0.833 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.9999 sample 14.566 us/op
ObservationBenchmark.observationWithoutThreadContention2:p1.00 sample 630.784 us/op
Click to view benchmark results Threads(30)

Benchmark Results

Baseline

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.baseline sample 8560658 6.501 ± 0.410 us/op
ObservationBenchmark.baseline:p0.00 sample ≈ 0 us/op
ObservationBenchmark.baseline:p0.50 sample 0.167 us/op
ObservationBenchmark.baseline:p0.90 sample 0.417 us/op
ObservationBenchmark.baseline:p0.95 sample 0.625 us/op
ObservationBenchmark.baseline:p0.99 sample 1.208 us/op
ObservationBenchmark.baseline:p0.999 sample 33.984 us/op
ObservationBenchmark.baseline:p0.9999 sample 19101.585 us/op
ObservationBenchmark.baseline:p1.00 sample 75759.616 us/op

Observation

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observation sample 6750419 17.321 ± 0.673 us/op
ObservationBenchmark.observation:p0.00 sample 0.541 us/op
ObservationBenchmark.observation:p0.50 sample 4.792 us/op
ObservationBenchmark.observation:p0.90 sample 6.416 us/op
ObservationBenchmark.observation:p0.95 sample 6.912 us/op
ObservationBenchmark.observation:p0.99 sample 8.160 us/op
ObservationBenchmark.observation:p0.999 sample 829.010 us/op
ObservationBenchmark.observation:p0.9999 sample 28736.160 us/op
ObservationBenchmark.observation:p1.00 sample 92143.616 us/op

Observation With optimisations (40f6268)

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observation2 sample 6840709 17.110 ± 0.709 us/op
ObservationBenchmark.observation2:p0.00 sample 0.458 us/op
ObservationBenchmark.observation2:p0.50 sample 4.624 us/op
ObservationBenchmark.observation2:p0.90 sample 6.080 us/op
ObservationBenchmark.observation2:p0.95 sample 6.576 us/op
ObservationBenchmark.observation2:p0.99 sample 7.952 us/op
ObservationBenchmark.observation2:p0.999 sample 736.256 us/op
ObservationBenchmark.observation2:p0.9999 sample 31195.136 us/op
ObservationBenchmark.observation2:p1.00 sample 92930.048 us/op

Observation Without Thread Contention

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observationWithoutThreadContention sample 267763 0.321 ± 0.037 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.00 sample 0.208 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.50 sample 0.292 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.90 sample 0.292 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.95 sample 0.334 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.99 sample 0.417 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.999 sample 1.416 us/op
ObservationBenchmark.observationWithoutThreadContention:p0.9999 sample 12.141 us/op
ObservationBenchmark.observationWithoutThreadContention:p1.00 sample 2727.936 us/op

Observation Without Thread Contention With optimisations (40f6268)

Benchmark Mode Cnt Score Error Units
ObservationBenchmark.observationWithoutThreadContention2 sample 283749 0.308 ± 0.019 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.00 sample 0.167 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.50 sample 0.292 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.90 sample 0.333 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.95 sample 0.334 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.99 sample 0.458 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.999 sample 0.833 us/op
ObservationBenchmark.observationWithoutThreadContention2:p0.9999 sample 11.736 us/op
ObservationBenchmark.observationWithoutThreadContention2:p1.00 sample 636.928 us/op

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.

Performance Degradation Due to Unnecessary Tag Sorting in DefaultMeterObservationHandler
2 participants