Repository navigation
Conversation
Reduce the number of times capacity growth is needed inside the StringWriter. A typical default SpringBoot Prometheus page has more than 11k characters. Best performance results when no capacity growth is needed at all, so base it on previous metrics page size plus some room for possible extra metric info.
Contributor
|
Hey @stokpop, thanks for the PR! I think the idea to remember the last scrape size is very nice. But i would not set the initial size (the one before the 1st scrape) to a fixed 12kb, instead we should use the defaults of the |
…itial 12k but the StringWriter default size.
Contributor
Author
|
@mhalbritter good idea, so that would be 16, the default size of StringWriter, I have made the update. |
mhalbritter
pushed a commit
that referenced
this pull request
Mar 9, 2022
Reduce the number of times capacity growth is needed inside the StringWriter. A typical default SpringBoot Prometheus page has more than 11k characters. Best performance results when no capacity growth is needed at all, so base it on previous metrics page size plus some room for possible extra metric info. See gh-30085
mhalbritter
added a commit
that referenced
this pull request
Mar 9, 2022
Contributor
|
Merged, thanks a lot for the contribution! |
Member
|
@mhalbritter and I discussed this a bit and we've decided that the unnecessary allocations are a performance bug. |
mhalbritter
pushed a commit
that referenced
this pull request
Mar 9, 2022
Reduce the number of times capacity growth is needed inside the StringWriter. A typical default SpringBoot Prometheus page has more than 11k characters. Best performance results when no capacity growth is needed at all, so base it on previous metrics page size plus some room for possible extra metric info. See gh-30085
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.
Reduce the number of times capacity growth is needed inside the StringWriter. A typical default SpringBoot Prometheus page has more than 11k characters. Best performance results when no capacity growth is needed at all, so base it on previous metrics page size plus some room for possible extra metric info.
Background
Profiling our SpringBoot application showed time spend in the
StringWriterofPrometheusScrapeEndpoint, and below that some time spend inArrays.copyof the wrappedStringBuilder.ensureCapacity. Default size is 16, so there will be multiple new array allocations and array copies during the filling of theStringWriter.This is below

TextFormat.writeOpenMetrics100:A quick gain might be to pre size the
StringWriterinPrometheusScrapeEndpoint.A JMH benchmark on local Mac M1 using
StringWriterwith different initial capacity show no substantial gain in ops/s. Effect might be different/better in virtualized container environment with less cpu power? The JMH benchmark does show significant memory allocation improvement ifStringWriteris created with initial actual size + some: can be around 3 times less.Bytes allocated per op, with different initial StringWriter sizes:

Bytes allocated with StringWriter

page size + 2:First tried with fixed
14 * 1024size, but that turns out to make it possibly worse when metrics page is a bit bigger than that and dynamic increase of backing array is 'too large' (e.g. see last column in first table). So then introduced apreviousMetricsScrapeSizeto hold size of last scrape and make newStringWriterthat size plus some more for possible new data.Not sure about actual improvement, but gut feeling is: less memory allocation, less objects (arrays) created to be garbage collected, less copying of arrays, and a component that is running in many places on earth will save some.
Final note: A default Prometheus metrics page is about 11k-12k characters. Adding additional metrics, e.g. via micrometer, will increase the size. We found that we used
MicrometerHttpClientInterceptorthat would add one line of metric info for each unique url, so that made 800k+ pages and had this issue magnified in profiling.