From e4fc8ab12224ae7359078f91179d7ff0de5fbb17 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 09:39:47 +0200 Subject: [PATCH 1/6] [Java] Quarkus: Switch to production recommended APIs and settings --- frameworks/quarkus-jvm/pom.xml | 8 +- .../java/com/httparena/BenchmarkResource.java | 74 +++---------------- .../main/java/com/httparena/StaticFiles.java | 24 ++++++ .../src/main/resources/application.properties | 9 ++- 4 files changed, 46 insertions(+), 69 deletions(-) create mode 100644 frameworks/quarkus-jvm/src/main/java/com/httparena/StaticFiles.java diff --git a/frameworks/quarkus-jvm/pom.xml b/frameworks/quarkus-jvm/pom.xml index e6298136..9dae1152 100644 --- a/frameworks/quarkus-jvm/pom.xml +++ b/frameworks/quarkus-jvm/pom.xml @@ -2,6 +2,7 @@ + 4.0.0 com.httparena @@ -39,17 +40,17 @@ org.xerial sqlite-jdbc - 3.47.2.0 + 3.51.3.0 org.postgresql postgresql - 42.7.4 + 42.7.10 com.zaxxer HikariCP - 6.2.1 + 7.0.2 @@ -70,4 +71,5 @@ + diff --git a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java index 813e3671..21e10617 100644 --- a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java +++ b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java @@ -3,7 +3,6 @@ import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import io.smallrye.common.annotation.NonBlocking; -import io.vertx.core.buffer.Buffer; import jakarta.annotation.PostConstruct; import jakarta.ws.rs.*; import jakarta.ws.rs.core.MediaType; @@ -15,20 +14,15 @@ import java.io.IOException; import java.io.InputStream; import java.net.URI; -import java.nio.charset.StandardCharsets; -import java.nio.file.Files; import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.util.*; -import java.util.concurrent.ConcurrentHashMap; @Path("/") public class BenchmarkResource { - private static final Buffer OK_BUFFER = Buffer.buffer("ok".getBytes(StandardCharsets.UTF_8)); - private final ObjectMapper mapper = new ObjectMapper(); private List> dataset; private byte[] largeJsonResponse; @@ -38,16 +32,6 @@ public class BenchmarkResource { private static final ThreadLocal tlConn = new ThreadLocal<>(); private static final ThreadLocal tlStmt = new ThreadLocal<>(); private HikariDataSource pgPool; - private final Map staticFiles = new ConcurrentHashMap<>(); - private static final Map MIME_TYPES = Map.ofEntries( - Map.entry(".css", "text/css"), - Map.entry(".js", "application/javascript"), - Map.entry(".html", "text/html"), - Map.entry(".woff2", "font/woff2"), - Map.entry(".svg", "image/svg+xml"), - Map.entry(".webp", "image/webp"), - Map.entry(".json", "application/json") - ); @PostConstruct public void init() throws IOException { @@ -98,36 +82,22 @@ public void init() throws IOException { pgPool = new HikariDataSource(config); } catch (Exception ignored) {} } - // Pre-load static files - File staticDir = new File("/data/static"); - if (staticDir.isDirectory()) { - File[] files = staticDir.listFiles(); - if (files != null) { - for (File sf : files) { - if (sf.isFile()) { - try { - staticFiles.put(sf.getName(), Files.readAllBytes(sf.toPath())); - } catch (IOException ignored) {} - } - } - } - } } @GET @Path("/pipeline") @Produces(MediaType.TEXT_PLAIN) @NonBlocking - public Buffer pipeline() { - return OK_BUFFER; + public String pipeline() { + return "ok"; } @GET @Path("/baseline11") @Produces(MediaType.TEXT_PLAIN) @NonBlocking - public String baselineGet(@QueryParam("a") String a, @QueryParam("b") String b) { - return String.valueOf(sumParams(a, b)); + public int baselineGet(@QueryParam("a") int a, @QueryParam("b") int b) { + return a + b; } @POST @@ -135,33 +105,29 @@ public String baselineGet(@QueryParam("a") String a, @QueryParam("b") String b) @Consumes(MediaType.TEXT_PLAIN) @Produces(MediaType.TEXT_PLAIN) @NonBlocking - public String baselinePost(@QueryParam("a") String a, @QueryParam("b") String b, String body) { - int sum = sumParams(a, b); - try { - sum += Integer.parseInt(body.trim()); - } catch (NumberFormatException ignored) {} - return String.valueOf(sum); + public int baselinePost(@QueryParam("a") int a, @QueryParam("b") int b, int body) { + return a + b + body; } @POST @Path("/upload") @Produces(MediaType.TEXT_PLAIN) - public String upload(InputStream body) throws IOException { + public long upload(InputStream body) throws IOException { byte[] buf = new byte[65536]; long total = 0; int n; while ((n = body.read(buf)) != -1) { total += n; } - return String.valueOf(total); + return total; } @GET @Path("/baseline2") @Produces(MediaType.TEXT_PLAIN) @NonBlocking - public String baseline2(@QueryParam("a") String a, @QueryParam("b") String b) { - return String.valueOf(sumParams(a, b)); + public int baseline2(@QueryParam("a") int a, @QueryParam("b") int b) { + return a + b; } @GET @@ -268,20 +234,6 @@ public byte[] compression() { return largeJsonResponse; } - @GET - @Path("/static/{filename}") - @NonBlocking - public jakarta.ws.rs.core.Response staticFile(@PathParam("filename") String filename) { - byte[] data = staticFiles.get(filename); - if (data == null) { - return jakarta.ws.rs.core.Response.status(404).build(); - } - int dot = filename.lastIndexOf('.'); - String ext = dot >= 0 ? filename.substring(dot) : ""; - String ct = MIME_TYPES.getOrDefault(ext, "application/octet-stream"); - return jakarta.ws.rs.core.Response.ok(data).header("Content-Type", ct).build(); - } - private PreparedStatement getDbStmt() { PreparedStatement stmt = tlStmt.get(); if (stmt != null) return stmt; @@ -297,10 +249,4 @@ private PreparedStatement getDbStmt() { return stmt; } - private int sumParams(String a, String b) { - int sum = 0; - if (a != null) try { sum += Integer.parseInt(a); } catch (NumberFormatException ignored) {} - if (b != null) try { sum += Integer.parseInt(b); } catch (NumberFormatException ignored) {} - return sum; - } } diff --git a/frameworks/quarkus-jvm/src/main/java/com/httparena/StaticFiles.java b/frameworks/quarkus-jvm/src/main/java/com/httparena/StaticFiles.java new file mode 100644 index 00000000..46ee9dcf --- /dev/null +++ b/frameworks/quarkus-jvm/src/main/java/com/httparena/StaticFiles.java @@ -0,0 +1,24 @@ +package com.httparena; + +import io.vertx.ext.web.Router; +import io.vertx.ext.web.handler.FileSystemAccess; +import io.vertx.ext.web.handler.StaticHandler; + +import jakarta.enterprise.context.ApplicationScoped; +import jakarta.enterprise.event.Observes; + +/** + * Serves the static resources in /data/static + * Recommended way to do in production workloads (besides using a nginx sidecar). + */ +@ApplicationScoped +public class StaticFiles { + + void init(@Observes Router router) { + var handler = StaticHandler.create(FileSystemAccess.ROOT, "/data/static"); + + router.route("/static/*") + .handler(handler); + } + +} diff --git a/frameworks/quarkus-jvm/src/main/resources/application.properties b/frameworks/quarkus-jvm/src/main/resources/application.properties index 81e9eaf2..0edfeb41 100644 --- a/frameworks/quarkus-jvm/src/main/resources/application.properties +++ b/frameworks/quarkus-jvm/src/main/resources/application.properties @@ -12,9 +12,14 @@ quarkus.http.ssl.client-auth=none # Allow 25MB request bodies for upload test quarkus.http.limits.max-body-size=25M +# Static files +quarkus.http.root-path=/static + +# Compression +quarkus.http.enable-compression=true + # TechEmpower-style tuning quarkus.http.accept-backlog=-1 -quarkus.http.idle-timeout=0 +quarkus.http.idle-timeout=30s quarkus.vertx.prefer-native-transport=true -quarkus.http.enable-compression=true quarkus.http.compression-level=1 From e80260c3d45e810b2f45925f879a7798ed93cad5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 09:51:36 +0200 Subject: [PATCH 2/6] Remove the root path setting --- .../quarkus-jvm/src/main/resources/application.properties | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/frameworks/quarkus-jvm/src/main/resources/application.properties b/frameworks/quarkus-jvm/src/main/resources/application.properties index 0edfeb41..39f0d308 100644 --- a/frameworks/quarkus-jvm/src/main/resources/application.properties +++ b/frameworks/quarkus-jvm/src/main/resources/application.properties @@ -10,10 +10,7 @@ quarkus.http.insecure-requests=enabled quarkus.http.ssl.client-auth=none # Allow 25MB request bodies for upload test -quarkus.http.limits.max-body-size=25M - -# Static files -quarkus.http.root-path=/static +quarkus.http.limits.max-body-size=25 # Compression quarkus.http.enable-compression=true From 559eafcdcea95bb9f1f8f7c1cf3fe13b74c89c61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 09:59:44 +0200 Subject: [PATCH 3/6] Revert to string result for upload - something broken there in Quarkus? --- .../src/main/java/com/httparena/BenchmarkResource.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java index 21e10617..1010bef1 100644 --- a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java +++ b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java @@ -112,14 +112,14 @@ public int baselinePost(@QueryParam("a") int a, @QueryParam("b") int b, int body @POST @Path("/upload") @Produces(MediaType.TEXT_PLAIN) - public long upload(InputStream body) throws IOException { + public String upload(InputStream body) throws IOException { byte[] buf = new byte[65536]; long total = 0; int n; while ((n = body.read(buf)) != -1) { total += n; } - return total; + return String.valueOf(total); } @GET From ded9fb2e3de0414df134ebadc4e919e88a3ef373 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 10:26:30 +0200 Subject: [PATCH 4/6] Try with a hint on stream consumption --- .../src/main/java/com/httparena/BenchmarkResource.java | 1 + 1 file changed, 1 insertion(+) diff --git a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java index 1010bef1..7d7bbaf2 100644 --- a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java +++ b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java @@ -111,6 +111,7 @@ public int baselinePost(@QueryParam("a") int a, @QueryParam("b") int b, int body @POST @Path("/upload") + @Consumes(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.TEXT_PLAIN) public String upload(InputStream body) throws IOException { byte[] buf = new byte[65536]; From f6b111a3bdad19243387260c11da34cd9b438a0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 10:30:04 +0200 Subject: [PATCH 5/6] Use built in java method --- .../main/java/com/httparena/BenchmarkResource.java | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java index 7d7bbaf2..41cc2087 100644 --- a/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java +++ b/frameworks/quarkus-jvm/src/main/java/com/httparena/BenchmarkResource.java @@ -13,6 +13,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; import java.net.URI; import java.sql.Connection; import java.sql.DriverManager; @@ -113,14 +114,8 @@ public int baselinePost(@QueryParam("a") int a, @QueryParam("b") int b, int body @Path("/upload") @Consumes(MediaType.APPLICATION_OCTET_STREAM) @Produces(MediaType.TEXT_PLAIN) - public String upload(InputStream body) throws IOException { - byte[] buf = new byte[65536]; - long total = 0; - int n; - while ((n = body.read(buf)) != -1) { - total += n; - } - return String.valueOf(total); + public long upload(InputStream body) throws IOException { + return body.transferTo(OutputStream.nullOutputStream()); } @GET From 4ef80ea85a1bbfd7c5d8e981f40094499e02afad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andreas=20N=C3=A4geli?= Date: Sun, 29 Mar 2026 12:02:59 +0200 Subject: [PATCH 6/6] Fix upload size limit --- .../quarkus-jvm/src/main/resources/application.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frameworks/quarkus-jvm/src/main/resources/application.properties b/frameworks/quarkus-jvm/src/main/resources/application.properties index 39f0d308..cc32d6b6 100644 --- a/frameworks/quarkus-jvm/src/main/resources/application.properties +++ b/frameworks/quarkus-jvm/src/main/resources/application.properties @@ -10,7 +10,7 @@ quarkus.http.insecure-requests=enabled quarkus.http.ssl.client-auth=none # Allow 25MB request bodies for upload test -quarkus.http.limits.max-body-size=25 +quarkus.http.limits.max-body-size=25M # Compression quarkus.http.enable-compression=true