schlosna opened a new pull request #352:
URL: https://github.com/apache/httpcomponents-client/pull/352
While analyzing some JFR profiles from a service utilizing a high volume of
async HTTP client requests, I noticed one of the top memory allocations of
`java.text.DecimalFormatSymbols` coming from
`org.apache.hc.client5.http.impl.ExecSupport#getNextExchangeId`, notably due to
use of `String#format`. Given that this seems to be on a hot code path, we can
optimize this code path.
Backtrace:
```
sun.util.locale.provider.DecimalFormatSymbolsProviderImpl.getInstance(Locale)
java.text.DecimalFormatSymbols.getInstance(Locale)
java.util.Formatter.zero()
java.util.Formatter$FormatSpecifier.getZero(Locale)
java.util.Formatter$FormatSpecifier.localizedMagnitude(StringBuilder,
CharSequence, int, Formatter$Flags, int, Locale)
java.util.Formatter$FormatSpecifier.print(long, Locale)
java.util.Formatter$FormatSpecifier.printInteger(Object, Locale)
java.util.Formatter$FormatSpecifier.print(Object, Locale)
java.util.Formatter.format(Locale, String, Object[])
java.util.Formatter.format(String, Object[])
java.lang.String.format(String, Object[])
org.apache.hc.client5.http.impl.ExecSupport.getNextExchangeId()
org.apache.hc.client5.http.impl.classic.InternalHttpClient.doExecute(HttpHost,
ClassicHttpRequest, HttpContext)
org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(ClassicHttpRequest,
HttpContext)
org.apache.hc.client5.http.impl.classic.CloseableHttpClient.execute(ClassicHttpRequest)
```
With a hand rolled a method to perform the same functionality of
`String.format("ex-%010d", long)` we see a roughly 20x speed-up in execution
time and ~16x reduction in allocations on a JMH microbenchmark for just this
function (see https://github.com/schlosna/httpclient-format-performance ). This
PR currently only optimizes the hot exchange ID code path and not the endpoint
ID code paths that use similar formatting (see
https://github.com/apache/httpcomponents-client/pull/249 )
Benchmarks all run on 16 core Intel(R) Xeon(R) Platinum 8259CL CPU @ 2.50GHz.
JDK 11.0.13, OpenJDK 64-Bit Server VM, 11.0.13+8-LTS
```
Benchmark Mode Cnt
Score Error Units
FormatBenchmarks.stringFormat avgt 5
674.730 ± 7.821 ns/op
FormatBenchmarks.stringFormat:·gc.alloc.rate avgt 5
852.757 ± 9.814 MB/sec
FormatBenchmarks.stringFormat:·gc.alloc.rate.norm avgt 5
704.000 ± 0.001 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space avgt 5
862.955 ± 171.696 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space.norm avgt 5
712.471 ± 146.197 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Old_Gen avgt 5
0.001 ± 0.002 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Old_Gen.norm avgt 5
0.001 ± 0.002 B/op
FormatBenchmarks.stringFormat:·gc.count avgt 5
53.000 counts
FormatBenchmarks.stringFormat:·gc.time avgt 5
33.000 ms
FormatBenchmarks.zeroPad avgt 5
38.760 ± 1.082 ns/op
FormatBenchmarks.zeroPad:·gc.alloc.rate avgt 5
1855.680 ± 51.458 MB/sec
FormatBenchmarks.zeroPad:·gc.alloc.rate.norm avgt 5
88.000 ± 0.001 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space avgt 5
1859.501 ± 202.606 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space.norm avgt 5
88.186 ± 10.045 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Old_Gen avgt 5
0.004 ± 0.002 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Old_Gen.norm avgt 5 ≈
10⁻⁴ B/op
FormatBenchmarks.zeroPad:·gc.count avgt 5
79.000 counts
FormatBenchmarks.zeroPad:·gc.time avgt 5
62.000 ms
```
JDK 15.0.5, OpenJDK 64-Bit Server VM, 15.0.5+3-MTS
```
Benchmark Mode Cnt
Score Error Units
FormatBenchmarks.stringFormat avgt 5
1081.263 ± 50.140 ns/op
FormatBenchmarks.stringFormat:·gc.alloc.rate avgt 5
1094.601 ± 50.204 MB/sec
FormatBenchmarks.stringFormat:·gc.alloc.rate.norm avgt 5
1448.105 ± 0.005 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space avgt 5
1093.372 ± 0.707 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space.norm avgt 5
1446.645 ± 67.105 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Survivor_Space avgt 5
0.004 ± 0.007 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Survivor_Space.norm avgt 5
0.006 ± 0.009 B/op
FormatBenchmarks.stringFormat:·gc.count avgt 5
55.000 counts
FormatBenchmarks.stringFormat:·gc.time avgt 5
51.000 ms
FormatBenchmarks.zeroPad avgt 5
39.612 ± 1.489 ns/op
FormatBenchmarks.zeroPad:·gc.alloc.rate avgt 5
1815.969 ± 68.124 MB/sec
FormatBenchmarks.zeroPad:·gc.alloc.rate.norm avgt 5
88.006 ± 0.001 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space avgt 5
1829.120 ± 209.669 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space.norm avgt 5
88.641 ± 9.053 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Survivor_Space avgt 5
0.008 ± 0.002 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Survivor_Space.norm avgt 5
≈ 10⁻³ B/op
FormatBenchmarks.zeroPad:·gc.count avgt 5
92.000 counts
FormatBenchmarks.zeroPad:·gc.time avgt 5
80.000 ms
```
JDK 17.0.1, OpenJDK 64-Bit Server VM, 17.0.1+12-LTS
```
Benchmark Mode Cnt
Score Error Units
FormatBenchmarks.stringFormat avgt 5
871.173 ± 11.990 ns/op
FormatBenchmarks.stringFormat:·gc.alloc.rate avgt 5
1313.506 ± 18.053 MB/sec
FormatBenchmarks.stringFormat:·gc.alloc.rate.norm avgt 5
1400.111 ± 0.011 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space avgt 5
1314.209 ± 139.635 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Eden_Space.norm avgt 5
1400.917 ± 157.487 B/op
FormatBenchmarks.stringFormat:·gc.churn.G1_Survivor_Space avgt 5
0.006 ± 0.008 MB/sec
FormatBenchmarks.stringFormat:·gc.churn.G1_Survivor_Space.norm avgt 5
0.006 ± 0.009 B/op
FormatBenchmarks.stringFormat:·gc.count avgt 5
81.000 counts
FormatBenchmarks.stringFormat:·gc.time avgt 5
53.000 ms
FormatBenchmarks.zeroPad avgt 5
41.057 ± 0.172 ns/op
FormatBenchmarks.zeroPad:·gc.alloc.rate avgt 5
1751.849 ± 7.370 MB/sec
FormatBenchmarks.zeroPad:·gc.alloc.rate.norm avgt 5
88.007 ± 0.001 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space avgt 5
1752.274 ± 171.164 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Eden_Space.norm avgt 5
88.027 ± 8.268 B/op
FormatBenchmarks.zeroPad:·gc.churn.G1_Survivor_Space avgt 5
0.009 ± 0.005 MB/sec
FormatBenchmarks.zeroPad:·gc.churn.G1_Survivor_Space.norm avgt 5
≈ 10⁻³ B/op
FormatBenchmarks.zeroPad:·gc.count avgt 5
108.000 counts
FormatBenchmarks.zeroPad:·gc.time avgt 5
69.000 ms
```
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]