-
Notifications
You must be signed in to change notification settings - Fork 3k
Description
Describe the bug
We were working on moving some code over from a non-Quarkus REST client to a Quarkus REST client. We noticed a massive drop in performance when we dit that, and got some very interesting results.
When using the Quarkus client to download a file from a URL as an InputStream, the creation of the InputStream object (So not actually streaming the file, but the creation of the InputStream
) scales worse than linearly with the size of the file you are downloading. Getting the InputStream however should take a constant amount of time and be milliseconds of work.
We ran a test against a set of object sizes we uploaded to MinIO (and thus the REST client simply sees a download link for the file):
1 * 1024, // 1KB
1 * 1024 * 1024, // 1MB
10 * 1024 * 1024, // 10MB
100 * 1024 * 1024, // 100MB
250 * 1024 * 1024, // 250MB
500 * 1024 * 1024, // 500MB
1L * 1024 * 1024 * 1024 // 1GB
The default REST client produced these results:
Downloading resource_1024_bytes_14840480614219054265.bin using Default REST client
Time to generate InputStream: 27 ms
Time to stream to file: 0 ms
Downloading resource_1048576_bytes_13817578619309500621.bin using Default REST client
Time to generate InputStream: 3 ms
Time to stream to file: 3 ms
Downloading resource_10485760_bytes_2310616242777621351.bin using Default REST client
Time to generate InputStream: 1 ms
Time to stream to file: 22 ms
Downloading resource_104857600_bytes_8607201645369659057.bin using Default REST client
Time to generate InputStream: 2 ms
Time to stream to file: 114 ms
Downloading resource_262144000_bytes_8533175391852326467.bin using Default REST client
Time to generate InputStream: 3 ms
Time to stream to file: 248 ms
Downloading resource_524288000_bytes_16558373151874773264.bin using Default REST client
Time to generate InputStream: 2 ms
Time to stream to file: 346 ms
Downloading resource_1073741824_bytes_14053281376256782222.bin using Default REST client
Time to generate InputStream: 2 ms
Time to stream to file: 686 ms
The Quarkus REST client however produced these results:
Downloading resource_1024_bytes_14840480614219054265.bin using Quarkus REST client
Time to generate InputStream: 68 ms
Time to stream to file: 0 ms
Downloading resource_1048576_bytes_13817578619309500621.bin using Quarkus REST client
Time to generate InputStream: 5 ms
Time to stream to file: 0 ms
Downloading resource_10485760_bytes_2310616242777621351.bin using Quarkus REST client
Time to generate InputStream: 16 ms
Time to stream to file: 3 ms
Downloading resource_104857600_bytes_8607201645369659057.bin using Quarkus REST client
Time to generate InputStream: 234 ms
Time to stream to file: 28 ms
Downloading resource_262144000_bytes_8533175391852326467.bin using Quarkus REST client
Time to generate InputStream: 1123 ms
Time to stream to file: 69 ms
Downloading resource_524288000_bytes_16558373151874773264.bin using Quarkus REST client
Time to generate InputStream: 3837 ms
Time to stream to file: 136 ms
Downloading resource_1073741824_bytes_14053281376256782222.bin using Quarkus REST client
Time to generate InputStream: 15140 ms
Time to stream to file: 268 ms
Expected behavior
Generating the InputStream
should take a few milliseconds and stay constant no matter how much data needs to be streamed
Actual behavior
The InputStream
generation scales with a time complexity that is worse than linear and takes over 15 seconds to create the InputStream for a 1GB file.
How to Reproduce?
- Clone the reproducer: https://gitlab.com/l.s.andringa1/quarkus-inputstream-reproducer
- Run
./gradlew quarkusRun
Output of uname -a
or ver
Ubuntu 25.04
Output of java -version
Java 21.0.7
Quarkus version or git rev
3.24.2
Build tool (ie. output of mvnw --version
or gradlew --version
)
Gradle 8.14.2
Additional information
No response