WebClient's first request is slow [SPR-17200] #21734
I discovered an issue with first request and shared state in WebClient. In short, the first request takes a lot of time to complete (~300 ms on my machine) compared to the following requests (~5 ms). The performance compared to RestTemplate is a bit problematic in case of integration tests with WireMock. I described more details in a repository with code examples: https://github.com/slonka/webclient-debug
I'd be grateful for some insights whether this can be improved via configuration or changes to WebClient source code that would initialize static fields eagerly before first request.
Please let me know if I can provide any more information.
Reference URL: https://github.com/slonka/webclient-debug
The text was updated successfully, but these errors were encountered:
Brian Clozel commented
Hello Krzysztof Slonka,
First, thanks for this very detailed report and repro project.
I ran your project with some modifications to the stats engine, and I also see slower calls for the first requests.
I've changed the classfiletransformer to also spy on reactor netty 0.7 classes, adding "reactor/ipc/netty"; here are the results:
It seems that a lot of comes from lazy initialization of the Netty pipeline/context/connection pool. Once this is done, the client is reusing existing connections in the connection pool. Also, depending on the platform, Netty will use native bindings (such as epoll on Linux), which could explain discrepancies between platforms. I haven't tried instrumenting Netty itself.
I've tried doing the same thing with Spring Boot 2.1.0.M1, since many changes were done in reactor netty 0.8 (a total rewrite of the client library) and Spring WebFlux itself. This time, we need to instrument "reactor/netty/http", since classes were relocated in the meantime.
Here are the results:
I think the API changes are making things more obvious that the first connection, channel setup and first response are at play here. The
Note that as of Spring Framework 5.1, you can also choose Jetty as a driver for
Given the current data, I'm not seeing anything we can do in the Spring Framework to improve that. Reactor Netty might be able to improve things, but Netty's model is probably important here.
Krzysztof Slonka commented
Thanks for your response.
I've added "reactor/ipc/netty" to instrumented libraries and the results are as follows:
As you can see that "reactor.ipc.netty" methods are on top.
Yes, and the results are as follows:
Not much changed in terms of timing, but URI Builder is no longer there (as you pointed out).
When using Netty4ClientHttpRequestFactory for RestTemplate, first request takes ~300 ms on my machine which is similar to WebClient.
When using JettyClientHttpConnector first request takes ~200 ms, which is better.
Considering everything we discussed here, what do you suggest using?
Brian Clozel commented
Thanks Krzysztof Slonka!
We've now come to the conclusion that this is tied to Netty's runtime model more than Spring itself. We're always looking into optimizations but this one looks like a tradeoff more than something we can work on.
My previous comment mentioned Jetty as an alternative client library, and this might be interesting if its runtime model suits you better.