spring-framework
spring-framework copied to clipboard
Slow webflux multipart upload
Hello,
We are developing a document submission application using WebFlux. However, we have noticed that handling multipart requests is slower with WebFlux compared to MVC. For example, when using MultipartFile in MVC, sending a 200MB file takes about 700ms, whereas it takes 4.2s with WebFlux (FilePart) and 4.5s with PartEvent.
Did we miss something?
Here is a repository reproducing the issue: Repo
Spring boot version : 3.4.4 Java 21
I suspected that when working in this area recently in #34178 and #34388 but was not 100% sure, but your report seems to confirm there is something to improve there, so I will try to have a deeper look.
What I saw was slow upload locally with big files, so I know how to reproduce even if for now, I am not sure about the reason.
Hello @sdeleuze
I’d like to contribute to this, may I ?
I've reduced the elapsed time from 4.2s to 700ms locally
Before:
~/IdeaProjects/WebfluxSlowMultipart git:[main]
curl -w "\nElapsed: %{time_total}s\n" \
-F file="@200mb.pdf" \
http://localhost:8080/part-event \
-o /dev/null -s
Elapsed: 4.260208s
~/IdeaProjects/WebfluxSlowMultipart git:[main]
curl -w "\nElapsed: %{time_total}s\n" \
-F file="@200mb.pdf" \
http://localhost:8080/file-part \
-o /dev/null -s
Elapsed: 4.346252s
After:
~/IdeaProjects/WebfluxSlowMultipart git:[main]
curl -w "\nElapsed: %{time_total}s\n" \
-F file="@200mb.pdf" \
http://localhost:8080/part-event \
-o /dev/null -s
Elapsed: 0.391556s
~/IdeaProjects/WebfluxSlowMultipart git:[main]
curl -w "\nElapsed: %{time_total}s\n" \
-F file="@200mb.pdf" \
http://localhost:8080/file-part \
-o /dev/null -s
Elapsed: 0.407896s
@xyraclius please share your findings, it is hard for us to tell you whether a contribution would be accepted if we don't know the type of changes you are working on.
A quick profiling session shows that NettyDataBuffer.getByte() is responsible here for most of the overhead. This is quite similar to an issue reported to Netty.
I think we should introduce an efficient variant in DataBuffer for traversing bytes from a DataBuffer, I have created #35623 for that. This is generally useful and in my tests this brings a x2 improvement. We would still need another x2 improvement to be on par with the multipart support from Servlet containers, but this is a good first step.