-
Notifications
You must be signed in to change notification settings - Fork 1k
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
Do not re-apply MeterFilters to IDs when registering if unnecessary #4856
Comments
If we agree that #3461 should be solved by making meter filters immutable this could be very simple. I already have an idea to tackle this issue and would open up a PR for that. The idea is to simplify the meterMap from |
Have you seen this (it eliminates the dynamic public class MeterDemo {
private static final SimpleMeterRegistry registry = new SimpleMeterRegistry();
private static final MeterProvider<Counter> counter = Counter.builder("test")
.tags("static", "1")
.withRegistry(registry);
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
counter.withTag("dynamic", String.valueOf(i)).increment();
}
System.out.println(registry.getMetersAsString());
}
}
I think you will have a new
Yes since the way you have the key for the lookup (
I'm looking at the benchmarks (the first image should be
I would recommend what you wrote: create a listener to listen to event when meters are removed.
Yepp, that's the issue, this is also why Micrometer does things in the way you explained above.
Could you please elaborate on this? You want Micrometer to store the Id before the filter and after too and do not run the filter when you found that mapping exists?
|
Yeah, I have seen it. This problem particularly deals with unneccessary overheads caused by running meterfilters everysingle time.
Yeah, exactly.
I don't think why someone would invoke same meter filter twice. But, even with that the mapping should be good since we are mapping from pre filtered id to final meter.
Yeah that's right. But, DistributionStatisticConfig is applied only when a meter is created for the first time. And this change wouldn't affect that. I have a PR with the initial thoughts here. Please have a look and we can discuss on that.
This is probably because I chose the simplest of the examples out there to demonstrate the changes. Usually, there will be multiple meter filters updating the Id's on the fly and that gets very complicated, and the memory could reach up to a few |
On another note, regarding the MeterProvider if the docs didn't cover it we should try to promote this in the docs. But in my initial benchmarks, I don't really see any sort of improvement using meter provider for this use-case. Never know I could have messed up and didn't measure the right thing. |
Right now you can write a filter that behaves like this: before noon it adds a tag |
Are those benchmarks somewhere we could look at and run?
We did have a user recently report having such a |
I have something you can try at /~https://github.com/lenin-jaganathan/micrometer-benchmark/blob/main/src/main/java/org/example/Comparison.java |
I hadn't thought about this possibility. From my perspective, it's a bad idea to use a filter for this. Using a |
@jonatan-ivanov I wasn't aware of the I noticed it was available for all meters except gauges, why? |
Mostly because gauges are async so you don't register them the same way you do other with |
I'm not sure what you mean with this, can you elaborate?
Let's take an example. In Vert.x we want to gauge the number of connections established on a TCP server. We have a I want a I cannot use a As a workaround, we use a wrapped builder that bounds a I don't think a Ideally, I'd like to be able to:
|
I gave I did some performance testing in our lab, using the plaintext and fortunes Techempower benchmarks.
In the plaintext benchmark, the change produced slightly less good results, but it's not bad at all considering there isn't a cache anymore. In the fortunes benchmark, which is more realistic (it involves a db query and html templating), the results are equivalent. So I think in Vert.x Micrometer Metrics we could consider dropping the custom cache at least. I'm going to give the benchmarks another try using the changes in #4857 |
@shakuzen I gave 1.13.0-RC1 a try and here are the results Plaintext benchmark: Fortunes benchmark: So 1.13.0-RC1 (with internal cache) provides slightly less performance than 1.12.4 (without cache). |
@tsegismont thank you for trying things out and providing the benchmark results. I'll keep looking into things as much as I can to see if we can't close the gap more. Let me know if you find anything in particular we can still improve.
Just to be clear, this means Micrometer 1.12.4 and Vert.x's meter cache? |
This was a comparison between:
|
Please describe the feature request.
To interact with a meter (recording values), the preferred pattern documented is to use the Builder to create a meter and interact with it. For example, the following code would create a counter,
Once the counter is created we would call the
counter.increment()
to increment the counter. For a simple counter like this, we can save it in a variable and call the increment method whenever we want to increment. Now, if we want to add a tag whose value will be available only during runtime, we cannot store it in a simple variable. There are two ways to do it,name
andtag
set we would get the same object all the time and can call increment on it. Again, so simple it seems but in a real-world scenario, applications would be having meterfilters registered which will have to be run every single time we invoke the builder. Since,Meter.Id
is immutable we keep on creating new meters if we want to add tags/modify tags/modify the name, etc. But all the code runs and would eventually return an already created meter in the registry. This becomes a huge overhead in the real-world use case where we interact with meters thousands of times per second and generate a very high amount of garbage data.1
, we tried a few different things and eventually used aHashMap
to store the different tags as the key and the returned meter as value. So, the next time you need the meter for a tag and name combination we would avoid all the intermediate steps and directly return the actual meter. This surely had a huge performance gain for us which is available in the above-mentioned repo. It opened up a few issues like,i. What if a meter is removed from the registry? Then our cache will be holding reference to a meter that is no longer reported and would be incrementing that. We then listened to the onMeterRemoved and removed the meters from the cache.
ii. What if someone added a meterfilter? That would basically invalidate all the meters. Micrometer doesn't enforce strict rules about when a filter can be added. But we sort approached meter registry state as a immutable thing and didn't want to invalidate the entire cache because that micrometer doesn't invalidate meters when meter filters are registered.
To address the above mentioned problem and to improve the overall performance of micrometer meters, a built-in way to map the preMapped Id's to mappedId's with O(1) retrieval time with minimal garbage generation could be introduced.
Reference:
Rationale
To make micrometer meter interaction faster and lightweight.
Additional Context
Some extent of this is also discussed in #3461
The text was updated successfully, but these errors were encountered: