diff --git a/frameworks/vertx/README.md b/frameworks/vertx/README.md
index 3c31f2536..c5a11dc89 100644
--- a/frameworks/vertx/README.md
+++ b/frameworks/vertx/README.md
@@ -17,6 +17,11 @@ Eclipse Vert.x with vertx-web on Netty, one server verticle per core.
| `/baseline11` | POST | Sums query parameters + request body |
| `/json/{count}?m=N` | GET | First `count` dataset items with `total = price * quantity * m` |
| `/upload` | POST | Streams the body and returns the byte count |
+| `/baseline2` | GET | Sums query parameter values |
+| `/async-db` | GET | Reads from PostgreSQL through the reactive pg client |
+| `/static/:filename` | GET | Serves a file from disk with `sendFile`, the brotli or gzip variant when the client accepts one |
+| `/crud/items` | GET/POST | Lists items by category with paging, or inserts one |
+| `/crud/items/:id` | GET/PUT | Reads one item through a Redis cache-aside, or updates it and drops the cached copy |
## Notes
@@ -25,3 +30,13 @@ Eclipse Vert.x with vertx-web on Netty, one server verticle per core.
- Compression through `HttpServerOptions.setCompressionSupported(true)`
- The verticle is deployed once per core, all instances sharing port 8080
- `/upload` is read from the request stream, so the 20 MB body is never buffered
+
+`json-tls` and `static-tls` listen on `8081` when `/certs/server.crt` and `/certs/server.key` are
+mounted. The verticle is deployed once per core and each instance binds both ports, so the TLS
+listener is spread across every event loop rather than parked on one. ALPN is off: those two
+profiles want HTTP/1.1 negotiated and no h2 offered.
+
+Static file bodies are read from disk on every request - `sendFile` hands the descriptor to the
+kernel rather than holding the bytes - and the pre-compressed sibling is picked per request.
+
+`tags` is a JSONB column, so the pg client hands back a `JsonArray` rather than text.
diff --git a/frameworks/vertx/meta.json b/frameworks/vertx/meta.json
index 61316b984..47c516fa1 100644
--- a/frameworks/vertx/meta.json
+++ b/frameworks/vertx/meta.json
@@ -19,7 +19,14 @@
"limited-conn",
"json",
"json-comp",
- "upload"
+ "json-tls",
+ "upload",
+ "static",
+ "static-tls",
+ "async-db",
+ "crud",
+ "api-4",
+ "api-16"
],
"maintainers": []
}
diff --git a/frameworks/vertx/pom.xml b/frameworks/vertx/pom.xml
index 045952db7..85b842d17 100644
--- a/frameworks/vertx/pom.xml
+++ b/frameworks/vertx/pom.xml
@@ -26,6 +26,22 @@
vertx-web
${vertx.version}
+
+ io.vertx
+ vertx-pg-client
+ ${vertx.version}
+
+
+
+ com.ongres.scram
+ scram-client
+ 3.1
+
+
+ io.vertx
+ vertx-redis-client
+ ${vertx.version}
+
diff --git a/frameworks/vertx/src/main/java/httparena/ServerVerticle.java b/frameworks/vertx/src/main/java/httparena/ServerVerticle.java
index d1f2988de..9ec195586 100644
--- a/frameworks/vertx/src/main/java/httparena/ServerVerticle.java
+++ b/frameworks/vertx/src/main/java/httparena/ServerVerticle.java
@@ -1,5 +1,7 @@
package httparena;
+import java.io.File;
+import java.util.List;
import java.util.Map;
import io.vertx.core.Future;
@@ -8,30 +10,77 @@
import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.JsonObject;
+import io.vertx.core.net.PemKeyCertOptions;
import io.vertx.ext.web.Router;
import io.vertx.ext.web.RoutingContext;
import io.vertx.ext.web.handler.BodyHandler;
+import io.vertx.pgclient.PgBuilder;
+import io.vertx.pgclient.PgConnectOptions;
+import io.vertx.redis.client.Redis;
+import io.vertx.redis.client.RedisAPI;
+import io.vertx.sqlclient.Pool;
+import io.vertx.sqlclient.PoolOptions;
+import io.vertx.sqlclient.Row;
+import io.vertx.sqlclient.Tuple;
public class ServerVerticle extends VerticleBase {
private static final long MAX_BODY = 25L * 1024 * 1024;
+ private static final String STATIC_ROOT = "/data/static";
+ private static final String CERT = "/certs/server.crt";
+ private static final String KEY = "/certs/server.key";
+
+ private static final String ITEM_COLUMNS =
+ "id, name, category, price, quantity, active, tags, rating_score, rating_count";
+
+ // The profile reads and writes the same ids, so a long TTL would answer from a copy
+ // the writes have already moved past.
+ private static final String CRUD_TTL_MS = "200";
private final JsonArray dataset;
+ private Pool pgPool;
+ private RedisAPI redis;
+
public ServerVerticle(JsonArray dataset) {
this.dataset = dataset;
}
@Override
public Future> start() {
+ String dbUrl = System.getenv("DATABASE_URL");
+ if (dbUrl != null && !dbUrl.isEmpty()) {
+ // The pool is per verticle instance and one is deployed per core, so the
+ // harness's connection budget is split across them rather than opened by each.
+ pgPool = PgBuilder.pool()
+ .connectingTo(PgConnectOptions.fromUri(dbUrl))
+ .with(new PoolOptions().setMaxSize(4))
+ .using(vertx)
+ .build();
+ }
+ String redisUrl = System.getenv("REDIS_URL");
+ if (redisUrl != null && !redisUrl.isEmpty()) {
+ redis = RedisAPI.api(Redis.createClient(vertx, redisUrl));
+ }
Router router = Router.router(vertx);
router.get("/pipeline").handler(ctx -> text(ctx, "ok"));
+ router.get("/baseline2").handler(this::baselineGet);
router.get("/baseline11").handler(this::baselineGet);
router.post("/baseline11")
.handler(BodyHandler.create().setBodyLimit(MAX_BODY))
.handler(this::baselinePost);
router.get("/json/:count").handler(this::jsonItems);
+ router.get("/async-db").handler(this::asyncDb);
+ router.get("/static/:filename").handler(this::staticFile);
+ router.get("/crud/items").handler(this::crudList);
+ router.post("/crud/items")
+ .handler(BodyHandler.create())
+ .handler(this::crudCreate);
+ router.get("/crud/items/:id").handler(this::crudRead);
+ router.put("/crud/items/:id")
+ .handler(BodyHandler.create())
+ .handler(this::crudUpdate);
router.post("/upload").handler(this::upload);
HttpServerOptions options = new HttpServerOptions()
@@ -39,13 +88,40 @@ public Future> start() {
.setPort(8080)
.setCompressionSupported(true);
- return vertx.createHttpServer(options).requestHandler(router).listen();
+ Future> plain = vertx.createHttpServer(options).requestHandler(router).listen();
+
+ // json-tls and static-tls on 8081, the same router behind TLS. This verticle is
+ // deployed once per core, so every instance binds both ports and the listener is
+ // spread across all the event loops rather than parked on one. ALPN is off: the
+ // two profiles want HTTP/1.1 negotiated and no h2 offered. The harness only mounts
+ // /certs for the TLS profiles.
+ if (new File(CERT).isFile() && new File(KEY).isFile()) {
+ HttpServerOptions tls = new HttpServerOptions()
+ .setHost("0.0.0.0")
+ .setPort(8081)
+ .setCompressionSupported(true)
+ .setSsl(true)
+ .setUseAlpn(false)
+ .setKeyCertOptions(new PemKeyCertOptions().setCertPath(CERT).setKeyPath(KEY));
+ return Future.all(plain, vertx.createHttpServer(tls).requestHandler(router).listen());
+ }
+ return plain;
}
private void text(RoutingContext ctx, String body) {
ctx.response().putHeader("content-type", "text/plain").end(body);
}
+ private void json(RoutingContext ctx, String body) {
+ ctx.response().putHeader("content-type", "application/json").end(body);
+ }
+
+ private void dbError(RoutingContext ctx, String message, int status) {
+ ctx.response().setStatusCode(status)
+ .putHeader("content-type", "application/json")
+ .end("{\"error\":\"" + message + "\"}");
+ }
+
private long querySum(RoutingContext ctx) {
long sum = 0;
for (Map.Entry entry : ctx.queryParams()) {
@@ -57,6 +133,16 @@ private long querySum(RoutingContext ctx) {
return sum;
}
+ private int intParam(RoutingContext ctx, String name, int fallback) {
+ String raw = ctx.queryParams().get(name);
+ if (raw == null) return fallback;
+ try {
+ return Integer.parseInt(raw.trim());
+ } catch (NumberFormatException e) {
+ return fallback;
+ }
+ }
+
private void baselineGet(RoutingContext ctx) {
text(ctx, Long.toString(querySum(ctx)));
}
@@ -100,6 +186,243 @@ private void jsonItems(RoutingContext ctx) {
ctx.json(new JsonObject().put("items", items).put("count", count));
}
+ // tags is a JSONB column, so the client hands back a JsonArray rather than text.
+ private JsonArray tags(Row row) {
+ Object value = row.getValue("tags");
+ if (value instanceof JsonArray array) return array;
+ if (value instanceof String text) return new JsonArray(text);
+ return new JsonArray();
+ }
+
+ private JsonObject itemShape(Row row) {
+ return new JsonObject()
+ .put("id", row.getLong("id"))
+ .put("name", row.getString("name"))
+ .put("category", row.getString("category"))
+ .put("price", row.getLong("price"))
+ .put("quantity", row.getLong("quantity"))
+ .put("active", row.getBoolean("active"))
+ .put("tags", tags(row))
+ .put("rating", new JsonObject()
+ .put("score", row.getLong("rating_score"))
+ .put("count", row.getLong("rating_count")));
+ }
+
+ private void asyncDb(RoutingContext ctx) {
+ if (pgPool == null) {
+ json(ctx, "{\"items\":[],\"count\":0}");
+ return;
+ }
+ int min = intParam(ctx, "min", 10);
+ int max = intParam(ctx, "max", 50);
+ int limit = Math.max(1, Math.min(50, intParam(ctx, "limit", 50)));
+
+ pgPool.preparedQuery("SELECT " + ITEM_COLUMNS + " FROM items WHERE price BETWEEN $1 AND $2 LIMIT $3")
+ .execute(Tuple.of(min, max, limit))
+ .onSuccess(rows -> {
+ JsonArray items = new JsonArray();
+ for (Row row : rows) items.add(itemShape(row));
+ json(ctx, new JsonObject().put("items", items).put("count", items.size()).encode());
+ })
+ .onFailure(e -> json(ctx, "{\"items\":[],\"count\":0}"));
+ }
+
+ // Standard mode still reads static bodies from disk on every request: sendFile hands
+ // the descriptor to the kernel rather than holding the bytes. The pre-compressed
+ // sibling is picked per request and is also read from disk.
+ private void staticFile(RoutingContext ctx) {
+ String filename = ctx.pathParam("filename");
+ if (filename == null || filename.contains("/") || filename.contains("..")) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ String path = STATIC_ROOT + "/" + filename;
+ if (!new File(path).isFile()) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ ctx.response().putHeader("content-type", contentType(filename));
+
+ String accept = ctx.request().getHeader("accept-encoding");
+ if (accept != null) {
+ if (accept.contains("br") && new File(path + ".br").isFile()) {
+ ctx.response().putHeader("content-encoding", "br").sendFile(path + ".br");
+ return;
+ }
+ if (accept.contains("gzip") && new File(path + ".gz").isFile()) {
+ ctx.response().putHeader("content-encoding", "gzip").sendFile(path + ".gz");
+ return;
+ }
+ }
+ ctx.response().sendFile(path);
+ }
+
+ private String contentType(String filename) {
+ int dot = filename.lastIndexOf('.');
+ String ext = dot < 0 ? "" : filename.substring(dot);
+ return switch (ext) {
+ case ".css" -> "text/css";
+ case ".js" -> "application/javascript";
+ case ".html" -> "text/html";
+ case ".woff2" -> "font/woff2";
+ case ".svg" -> "image/svg+xml";
+ case ".webp" -> "image/webp";
+ case ".json" -> "application/json";
+ default -> "application/octet-stream";
+ };
+ }
+
+ private void crudList(RoutingContext ctx) {
+ if (pgPool == null) {
+ dbError(ctx, "DB not available", 500);
+ return;
+ }
+ String category = ctx.queryParams().get("category");
+ if (category == null) category = "electronics";
+ int page = Math.max(1, intParam(ctx, "page", 1));
+ int limit = Math.max(1, Math.min(50, intParam(ctx, "limit", 10)));
+
+ pgPool.preparedQuery("SELECT " + ITEM_COLUMNS + " FROM items WHERE category = $1 ORDER BY id LIMIT $2 OFFSET $3")
+ .execute(Tuple.of(category, limit, (page - 1) * limit))
+ .onSuccess(rows -> {
+ JsonArray items = new JsonArray();
+ for (Row row : rows) items.add(itemShape(row));
+ json(ctx, new JsonObject()
+ .put("items", items)
+ .put("total", items.size())
+ .put("page", page)
+ .put("limit", limit)
+ .encode());
+ })
+ .onFailure(e -> dbError(ctx, "query failed", 500));
+ }
+
+ private void crudCreate(RoutingContext ctx) {
+ if (pgPool == null) {
+ dbError(ctx, "DB not available", 500);
+ return;
+ }
+ JsonObject body = ctx.body().asJsonObject();
+ if (body == null) {
+ dbError(ctx, "insert failed", 500);
+ return;
+ }
+ pgPool.preparedQuery("INSERT INTO items (id, name, category, price, quantity, active, tags, rating_score, rating_count) "
+ + "VALUES ($1, $2, $3, $4, $5, true, '[\"bench\"]', 0, 0) "
+ + "ON CONFLICT (id) DO UPDATE SET name = $2, price = $4, quantity = $5 RETURNING id")
+ .execute(Tuple.of(
+ body.getLong("id"),
+ body.getString("name", "New Product"),
+ body.getString("category", "test"),
+ body.getLong("price", 0L),
+ body.getLong("quantity", 0L)))
+ .onSuccess(rows -> ctx.response().setStatusCode(201)
+ .putHeader("content-type", "application/json")
+ .end(new JsonObject()
+ .put("id", rows.iterator().next().getLong("id"))
+ .put("name", body.getValue("name"))
+ .put("category", body.getValue("category"))
+ .put("price", body.getValue("price"))
+ .put("quantity", body.getValue("quantity"))
+ .encode()))
+ .onFailure(e -> dbError(ctx, "insert failed", 500));
+ }
+
+ // Cache-aside on Redis where the harness provides it - crud is the one profile that
+ // does, and the cache is shared across every verticle instance.
+ private void crudRead(RoutingContext ctx) {
+ if (pgPool == null) {
+ dbError(ctx, "DB not available", 500);
+ return;
+ }
+ long id;
+ try {
+ id = Long.parseLong(ctx.pathParam("id"));
+ } catch (NumberFormatException e) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ String key = "crud:" + id;
+ if (redis == null) {
+ crudReadFromDb(ctx, id, key);
+ return;
+ }
+ redis.get(key)
+ .onSuccess(hit -> {
+ if (hit != null) {
+ ctx.response()
+ .putHeader("content-type", "application/json")
+ .putHeader("x-cache", "HIT")
+ .end(hit.toString());
+ } else {
+ crudReadFromDb(ctx, id, key);
+ }
+ })
+ .onFailure(e -> crudReadFromDb(ctx, id, key));
+ }
+
+ private void crudReadFromDb(RoutingContext ctx, long id, String key) {
+ pgPool.preparedQuery("SELECT " + ITEM_COLUMNS + " FROM items WHERE id = $1 LIMIT 1")
+ .execute(Tuple.of(id))
+ .onSuccess(rows -> {
+ if (rows.size() == 0) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ String body = itemShape(rows.iterator().next()).encode();
+ if (redis != null) {
+ redis.set(List.of(key, body, "PX", CRUD_TTL_MS));
+ }
+ ctx.response()
+ .putHeader("content-type", "application/json")
+ .putHeader("x-cache", "MISS")
+ .end(body);
+ })
+ .onFailure(e -> dbError(ctx, "query failed", 500));
+ }
+
+ private void crudUpdate(RoutingContext ctx) {
+ if (pgPool == null) {
+ dbError(ctx, "DB not available", 500);
+ return;
+ }
+ long id;
+ try {
+ id = Long.parseLong(ctx.pathParam("id"));
+ } catch (NumberFormatException e) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ JsonObject body = ctx.body().asJsonObject();
+ if (body == null) {
+ dbError(ctx, "update failed", 500);
+ return;
+ }
+ long finalId = id;
+ pgPool.preparedQuery("UPDATE items SET name = $1, price = $2, quantity = $3 WHERE id = $4")
+ .execute(Tuple.of(
+ body.getString("name", "Updated"),
+ body.getLong("price", 0L),
+ body.getLong("quantity", 0L),
+ id))
+ .onSuccess(rows -> {
+ if (rows.rowCount() == 0) {
+ ctx.response().setStatusCode(404).end();
+ return;
+ }
+ if (redis != null) {
+ redis.del(List.of("crud:" + finalId));
+ }
+ json(ctx, new JsonObject()
+ .put("id", finalId)
+ .put("name", body.getValue("name"))
+ .put("price", body.getValue("price"))
+ .put("quantity", body.getValue("quantity"))
+ .encode());
+ })
+ .onFailure(e -> dbError(ctx, "update failed", 500));
+ }
+
private void upload(RoutingContext ctx) {
HttpServerRequest request = ctx.request();
long[] size = {0};
diff --git a/site/data/results/vertx.json b/site/data/results/vertx.json
index a31cad606..70cc18f31 100644
--- a/site/data/results/vertx.json
+++ b/site/data/results/vertx.json
@@ -1,22 +1,94 @@
{
"framework": "vertx",
"results": {
+ "api-16-1024": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 104880,
+ "avg_latency": "8.31ms",
+ "p99_latency": "84.30ms",
+ "cpu": "1580.4%",
+ "memory": "2.0GiB",
+ "connections": 1024,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "524.16MB/s",
+ "input_bw": "5.90MB/s",
+ "reconnects": 314499,
+ "status_2xx": 1573208,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0,
+ "tpl_baseline": 588640,
+ "tpl_json": 590836,
+ "tpl_db": 0,
+ "tpl_upload": 0,
+ "tpl_static": 0,
+ "tpl_async_db": 393731
+ },
+ "api-4-256": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 29786,
+ "avg_latency": "7.76ms",
+ "p99_latency": "92.40ms",
+ "cpu": "396.3%",
+ "memory": "618MiB",
+ "connections": 256,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "148.70MB/s",
+ "input_bw": "1.68MB/s",
+ "reconnects": 89335,
+ "status_2xx": 446803,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0,
+ "tpl_baseline": 167473,
+ "tpl_json": 167233,
+ "tpl_db": 0,
+ "tpl_upload": 0,
+ "tpl_static": 0,
+ "tpl_async_db": 112097
+ },
+ "async-db-1024": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 198525,
+ "avg_latency": "4.72ms",
+ "p99_latency": "47.00ms",
+ "cpu": "4772.4%",
+ "memory": "5.1GiB",
+ "connections": 1024,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "750.36MB/s",
+ "input_bw": "13.25MB/s",
+ "reconnects": 79391,
+ "status_2xx": 1985254,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
"baseline-4096": {
"framework": "vertx",
"language": "Java",
- "rps": 2060804,
- "avg_latency": "1.99ms",
- "p99_latency": "5.03ms",
- "cpu": "6246.7%",
- "memory": "4.5GiB",
+ "rps": 1994369,
+ "avg_latency": "2.06ms",
+ "p99_latency": "5.07ms",
+ "cpu": "6290.9%",
+ "memory": "4.8GiB",
"connections": 4096,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "129.68MB/s",
- "input_bw": "159.19MB/s",
+ "bandwidth": "125.50MB/s",
+ "input_bw": "154.06MB/s",
"reconnects": 0,
- "status_2xx": 10304024,
+ "status_2xx": 9971849,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -24,19 +96,39 @@
"baseline-512": {
"framework": "vertx",
"language": "Java",
- "rps": 2072254,
- "avg_latency": "246us",
- "p99_latency": "460us",
- "cpu": "6418.1%",
- "memory": "3.3GiB",
+ "rps": 2042479,
+ "avg_latency": "250us",
+ "p99_latency": "468us",
+ "cpu": "6487.6%",
+ "memory": "2.8GiB",
"connections": 512,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "130.39MB/s",
- "input_bw": "160.08MB/s",
+ "bandwidth": "128.53MB/s",
+ "input_bw": "157.78MB/s",
"reconnects": 0,
- "status_2xx": 10361272,
+ "status_2xx": 10212399,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "crud-4096": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 226986,
+ "avg_latency": "18.03ms",
+ "p99_latency": "62.80ms",
+ "cpu": "4087.6%",
+ "memory": "2.9GiB",
+ "connections": 4096,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "64.18MB/s",
+ "input_bw": "19.48MB/s",
+ "reconnects": 15028,
+ "status_2xx": 3404796,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -44,19 +136,19 @@
"json-4096": {
"framework": "vertx",
"language": "Java",
- "rps": 688783,
- "avg_latency": "5.66ms",
- "p99_latency": "22.90ms",
- "cpu": "6242.5%",
- "memory": "11.4GiB",
+ "rps": 671315,
+ "avg_latency": "5.80ms",
+ "p99_latency": "29.90ms",
+ "cpu": "6382.1%",
+ "memory": "6.6GiB",
"connections": 4096,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "2.30GB/s",
- "input_bw": "32.84MB/s",
- "reconnects": 135929,
- "status_2xx": 3443915,
+ "bandwidth": "2.25GB/s",
+ "input_bw": "32.01MB/s",
+ "reconnects": 132671,
+ "status_2xx": 3356579,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -64,19 +156,19 @@
"json-comp-16384": {
"framework": "vertx",
"language": "Java",
- "rps": 256936,
- "avg_latency": "63.14ms",
- "p99_latency": "149.40ms",
- "cpu": "6245.0%",
- "memory": "12.8GiB",
+ "rps": 256570,
+ "avg_latency": "63.01ms",
+ "p99_latency": "146.90ms",
+ "cpu": "6181.9%",
+ "memory": "15.2GiB",
"connections": 16384,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "330.58MB/s",
- "input_bw": "19.11MB/s",
- "reconnects": 44713,
- "status_2xx": 1284683,
+ "bandwidth": "330.20MB/s",
+ "input_bw": "19.09MB/s",
+ "reconnects": 44005,
+ "status_2xx": 1282851,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -84,19 +176,19 @@
"json-comp-4096": {
"framework": "vertx",
"language": "Java",
- "rps": 259189,
- "avg_latency": "15.78ms",
- "p99_latency": "43.40ms",
- "cpu": "5997.8%",
- "memory": "6.7GiB",
+ "rps": 256544,
+ "avg_latency": "15.94ms",
+ "p99_latency": "45.40ms",
+ "cpu": "6095.9%",
+ "memory": "6.4GiB",
"connections": 4096,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "333.51MB/s",
- "input_bw": "19.28MB/s",
- "reconnects": 50044,
- "status_2xx": 1295945,
+ "bandwidth": "330.08MB/s",
+ "input_bw": "19.08MB/s",
+ "reconnects": 49511,
+ "status_2xx": 1282722,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -104,19 +196,38 @@
"json-comp-512": {
"framework": "vertx",
"language": "Java",
- "rps": 259837,
- "avg_latency": "1.97ms",
- "p99_latency": "8.95ms",
- "cpu": "6166.2%",
+ "rps": 257543,
+ "avg_latency": "1.98ms",
+ "p99_latency": "8.92ms",
+ "cpu": "6182.5%",
"memory": "4.1GiB",
"connections": 512,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "334.34MB/s",
- "input_bw": "19.33MB/s",
- "reconnects": 51952,
- "status_2xx": 1299185,
+ "bandwidth": "331.36MB/s",
+ "input_bw": "19.16MB/s",
+ "reconnects": 51502,
+ "status_2xx": 1287716,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "json-tls-4096": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 601618,
+ "avg_latency": "7.37ms",
+ "p99_latency": "134.88ms",
+ "cpu": "6181.7%",
+ "memory": "8.0GiB",
+ "connections": 4096,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "2.01GB",
+ "reconnects": 0,
+ "status_2xx": 3067146,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -124,19 +235,19 @@
"limited-conn-4096": {
"framework": "vertx",
"language": "Java",
- "rps": 605570,
- "avg_latency": "6.71ms",
- "p99_latency": "68.60ms",
- "cpu": "3343.8%",
- "memory": "2.3GiB",
+ "rps": 602586,
+ "avg_latency": "6.77ms",
+ "p99_latency": "68.70ms",
+ "cpu": "3254.6%",
+ "memory": "2.4GiB",
"connections": 4096,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "38.10MB/s",
- "input_bw": "46.78MB/s",
- "reconnects": 302831,
- "status_2xx": 3027853,
+ "bandwidth": "37.92MB/s",
+ "input_bw": "46.55MB/s",
+ "reconnects": 301293,
+ "status_2xx": 3012933,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -144,19 +255,19 @@
"limited-conn-512": {
"framework": "vertx",
"language": "Java",
- "rps": 600428,
- "avg_latency": "845us",
- "p99_latency": "8.29ms",
- "cpu": "3301.4%",
+ "rps": 583157,
+ "avg_latency": "870us",
+ "p99_latency": "8.54ms",
+ "cpu": "3191.5%",
"memory": "2.4GiB",
"connections": 512,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "37.78MB/s",
- "input_bw": "46.38MB/s",
- "reconnects": 300212,
- "status_2xx": 3002141,
+ "bandwidth": "36.69MB/s",
+ "input_bw": "45.05MB/s",
+ "reconnects": 291584,
+ "status_2xx": 2915789,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -164,18 +275,18 @@
"pipelined-4096": {
"framework": "vertx",
"language": "Java",
- "rps": 11211420,
- "avg_latency": "5.86ms",
- "p99_latency": "14.60ms",
- "cpu": "6099.4%",
- "memory": "6.2GiB",
+ "rps": 11782768,
+ "avg_latency": "5.58ms",
+ "p99_latency": "13.40ms",
+ "cpu": "6288.8%",
+ "memory": "7.3GiB",
"connections": 4096,
"threads": 64,
"duration": "5s",
"pipeline": 16,
- "bandwidth": "705.50MB/s",
+ "bandwidth": "741.43MB/s",
"reconnects": 0,
- "status_2xx": 56057104,
+ "status_2xx": 58913840,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -183,18 +294,132 @@
"pipelined-512": {
"framework": "vertx",
"language": "Java",
- "rps": 11418576,
- "avg_latency": "716us",
- "p99_latency": "3.60ms",
- "cpu": "6154.3%",
- "memory": "5.7GiB",
+ "rps": 12414412,
+ "avg_latency": "659us",
+ "p99_latency": "3.55ms",
+ "cpu": "6192.5%",
+ "memory": "5.2GiB",
"connections": 512,
"threads": 64,
"duration": "5s",
"pipeline": 16,
- "bandwidth": "718.53MB/s",
+ "bandwidth": "781.18MB/s",
+ "reconnects": 0,
+ "status_2xx": 62072064,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-1024": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 230227,
+ "avg_latency": "4.51ms",
+ "p99_latency": "43.67ms",
+ "cpu": "6447.1%",
+ "memory": "2.8GiB",
+ "connections": 1024,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "3.51GB",
+ "reconnects": 0,
+ "status_2xx": 1174059,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-4096": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 227767,
+ "avg_latency": "17.96ms",
+ "p99_latency": "96.37ms",
+ "cpu": "6441.7%",
+ "memory": "3.1GiB",
+ "connections": 4096,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "3.48GB",
+ "reconnects": 0,
+ "status_2xx": 1161592,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-6800": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 226617,
+ "avg_latency": "29.86ms",
+ "p99_latency": "148.10ms",
+ "cpu": "6321.8%",
+ "memory": "3.2GiB",
+ "connections": 6800,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "3.46GB",
+ "reconnects": 0,
+ "status_2xx": 1155791,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-tls-1024": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 195103,
+ "avg_latency": "5.40ms",
+ "p99_latency": "49.58ms",
+ "cpu": "6204.9%",
+ "memory": "1.6GiB",
+ "connections": 1024,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "2.98GB",
+ "reconnects": 0,
+ "status_2xx": 994981,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-tls-4096": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 191689,
+ "avg_latency": "21.44ms",
+ "p99_latency": "183.98ms",
+ "cpu": "6313.9%",
+ "memory": "3.4GiB",
+ "connections": 4096,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "2.93GB",
+ "reconnects": 0,
+ "status_2xx": 977503,
+ "status_3xx": 0,
+ "status_4xx": 0,
+ "status_5xx": 0
+ },
+ "static-tls-6800": {
+ "framework": "vertx",
+ "language": "Java",
+ "rps": 187031,
+ "avg_latency": "36.14ms",
+ "p99_latency": "235.22ms",
+ "cpu": "6282.1%",
+ "memory": "2.8GiB",
+ "connections": 6800,
+ "threads": 64,
+ "duration": "5s",
+ "pipeline": 1,
+ "bandwidth": "2.85GB",
"reconnects": 0,
- "status_2xx": 57092880,
+ "status_2xx": 953524,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -202,19 +427,19 @@
"upload-256": {
"framework": "vertx",
"language": "Java",
- "rps": 2029,
- "avg_latency": "122.87ms",
- "p99_latency": "680.90ms",
- "cpu": "6011.4%",
- "memory": "8.9GiB",
+ "rps": 2148,
+ "avg_latency": "116.81ms",
+ "p99_latency": "683.80ms",
+ "cpu": "6072.8%",
+ "memory": "9.7GiB",
"connections": 256,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "141.20KB/s",
- "input_bw": "16.09GB/s",
- "reconnects": 1982,
- "status_2xx": 10145,
+ "bandwidth": "149.50KB/s",
+ "input_bw": "17.04GB/s",
+ "reconnects": 2110,
+ "status_2xx": 10744,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
@@ -222,19 +447,19 @@
"upload-32": {
"framework": "vertx",
"language": "Java",
- "rps": 2105,
- "avg_latency": "15.17ms",
- "p99_latency": "62.10ms",
- "cpu": "2628.5%",
+ "rps": 1846,
+ "avg_latency": "17.30ms",
+ "p99_latency": "73.30ms",
+ "cpu": "2664.8%",
"memory": "7.8GiB",
"connections": 32,
"threads": 64,
"duration": "5s",
"pipeline": 1,
- "bandwidth": "146.41KB/s",
- "input_bw": "16.70GB/s",
- "reconnects": 2106,
- "status_2xx": 10525,
+ "bandwidth": "128.43KB/s",
+ "input_bw": "14.64GB/s",
+ "reconnects": 1846,
+ "status_2xx": 9233,
"status_3xx": 0,
"status_4xx": 0,
"status_5xx": 0
diff --git a/site/static/logs/api-16/1024/vertx.log b/site/static/logs/api-16/1024/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/api-4/256/vertx.log b/site/static/logs/api-4/256/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/async-db/1024/vertx.log b/site/static/logs/async-db/1024/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/crud/4096/vertx.log b/site/static/logs/crud/4096/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/json-tls/4096/vertx.log b/site/static/logs/json-tls/4096/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static-tls/1024/vertx.log b/site/static/logs/static-tls/1024/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static-tls/4096/vertx.log b/site/static/logs/static-tls/4096/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static-tls/6800/vertx.log b/site/static/logs/static-tls/6800/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static/1024/vertx.log b/site/static/logs/static/1024/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static/4096/vertx.log b/site/static/logs/static/4096/vertx.log
new file mode 100644
index 000000000..e69de29bb
diff --git a/site/static/logs/static/6800/vertx.log b/site/static/logs/static/6800/vertx.log
new file mode 100644
index 000000000..e69de29bb