Skip to content

Commit 26f768b

Browse files
committed
Add mixed test
1 parent a3690c9 commit 26f768b

65 files changed

Lines changed: 2478 additions & 669 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

data/benchmark.db

7.99 MB
Binary file not shown.

frameworks/aspnet-minimal/Program.cs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using System.Security.Cryptography.X509Certificates;
44
using Microsoft.AspNetCore.ResponseCompression;
55
using Microsoft.AspNetCore.Server.Kestrel.Core;
6+
using Microsoft.Data.Sqlite;
67

78
var builder = WebApplication.CreateBuilder(args);
89
builder.Logging.ClearProviders();
@@ -113,6 +114,50 @@
113114
}
114115
}
115116

117+
// Open SQLite database
118+
SqliteConnection? dbConn = null;
119+
var dbPath = "/data/benchmark.db";
120+
if (File.Exists(dbPath))
121+
{
122+
dbConn = new SqliteConnection($"Data Source={dbPath};Mode=ReadOnly");
123+
dbConn.Open();
124+
using var pragma = dbConn.CreateCommand();
125+
pragma.CommandText = "PRAGMA mmap_size=268435456";
126+
pragma.ExecuteNonQuery();
127+
}
128+
129+
app.MapGet("/db", (HttpRequest req) =>
130+
{
131+
if (dbConn == null)
132+
return Results.Problem("DB not available");
133+
double min = 10, max = 50;
134+
if (req.Query.ContainsKey("min") && double.TryParse(req.Query["min"], out double pmin))
135+
min = pmin;
136+
if (req.Query.ContainsKey("max") && double.TryParse(req.Query["max"], out double pmax))
137+
max = pmax;
138+
using var cmd = dbConn.CreateCommand();
139+
cmd.CommandText = "SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN @min AND @max LIMIT 50";
140+
cmd.Parameters.AddWithValue("@min", min);
141+
cmd.Parameters.AddWithValue("@max", max);
142+
using var reader = cmd.ExecuteReader();
143+
var items = new List<object>();
144+
while (reader.Read())
145+
{
146+
items.Add(new
147+
{
148+
id = reader.GetInt32(0),
149+
name = reader.GetString(1),
150+
category = reader.GetString(2),
151+
price = reader.GetDouble(3),
152+
quantity = reader.GetInt32(4),
153+
active = reader.GetInt32(5) == 1,
154+
tags = JsonSerializer.Deserialize<List<string>>(reader.GetString(6)),
155+
rating = new { score = reader.GetDouble(7), count = reader.GetInt32(8) },
156+
});
157+
}
158+
return Results.Json(new { items, count = items.Count });
159+
});
160+
116161
app.MapGet("/static/{filename}", (string filename) =>
117162
{
118163
if (staticFileMap.TryGetValue(filename, out var sf))

frameworks/aspnet-minimal/aspnet-minimal.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,7 @@
33
<TargetFramework>net10.0</TargetFramework>
44
<ImplicitUsings>enable</ImplicitUsings>
55
</PropertyGroup>
6+
<ItemGroup>
7+
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.3" />
8+
</ItemGroup>
69
</Project>

frameworks/aspnet-minimal/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"upload",
1515
"compression",
1616
"noisy",
17+
"mixed",
1718
"baseline-h2",
1819
"static-h2",
1920
"baseline-h3",

frameworks/bun/meta.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
"display_name": "bun",
33
"language": "TS",
44
"type": "realistic",
5-
"engine": "JavaScriptCore",
5+
"engine": "JSC",
66
"description": "Bun's built-in HTTP server using JavaScriptCore engine with multi-core clustering.",
77
"repo": "https://github.com/oven-sh/bun",
88
"enabled": true,
@@ -14,6 +14,7 @@
1414
"upload",
1515
"compression",
1616
"noisy",
17+
"mixed",
1718
"baseline-h2",
1819
"static-h2"
1920
]

frameworks/bun/server.ts

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
const zlib = require("zlib");
22
const fs = require("fs");
3+
const { Database } = require("bun:sqlite");
34

45
const MIME_TYPES: Record<string, string> = {
56
".css": "text/css", ".js": "application/javascript", ".html": "text/html",
@@ -26,6 +27,19 @@ const largeItems = largeData.map((d: any) => ({
2627
}));
2728
const largeJsonBuf = Buffer.from(JSON.stringify({ items: largeItems, count: largeItems.length }));
2829

30+
// Open SQLite database read-only (retry on transient failure)
31+
let dbStmt: any = null;
32+
for (let attempt = 0; attempt < 3 && !dbStmt; attempt++) {
33+
try {
34+
const db = new Database("/data/benchmark.db", { readonly: true });
35+
db.exec("PRAGMA mmap_size=268435456");
36+
dbStmt = db.prepare("SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN ? AND ? LIMIT 50");
37+
} catch (e) {
38+
console.error(`SQLite open attempt ${attempt + 1} failed:`, e);
39+
if (attempt < 2) Bun.sleepSync(50);
40+
}
41+
}
42+
2943
// Pre-load static files
3044
const staticFiles: Record<string, { buf: Buffer; ct: string }> = {};
3145
try {
@@ -61,6 +75,36 @@ function handleRequest(req: Request): Response | Promise<Response> {
6175
const qIdx = url.indexOf("?", pathStart);
6276
const path = qIdx === -1 ? url.slice(pathStart) : url.slice(pathStart, qIdx);
6377

78+
if (path === "/db") {
79+
if (!dbStmt) return new Response("DB not available", { status: 500 });
80+
try {
81+
let min = 10, max = 50;
82+
if (qIdx !== -1) {
83+
const qs = url.slice(qIdx + 1);
84+
for (const pair of qs.split("&")) {
85+
const eq = pair.indexOf("=");
86+
if (eq === -1) continue;
87+
const k = pair.slice(0, eq), v = pair.slice(eq + 1);
88+
if (k === "min") min = parseFloat(v) || 10;
89+
else if (k === "max") max = parseFloat(v) || 50;
90+
}
91+
}
92+
const rows = dbStmt.all(min, max) as any[];
93+
const items = rows.map((r: any) => ({
94+
id: r.id, name: r.name, category: r.category,
95+
price: r.price, quantity: r.quantity, active: r.active === 1,
96+
tags: JSON.parse(r.tags),
97+
rating: { score: r.rating_score, count: r.rating_count },
98+
}));
99+
const body = JSON.stringify({ items, count: items.length });
100+
return new Response(body, {
101+
headers: { "content-type": "application/json" },
102+
});
103+
} catch (e: any) {
104+
return new Response(e.message || "db error", { status: 500 });
105+
}
106+
}
107+
64108
if (path === "/pipeline") {
65109
return new Response("ok", { headers: { "content-type": "text/plain" } });
66110
}

frameworks/caddy/go.mod

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@ module httparena-handler
22

33
go 1.24
44

5-
require github.com/caddyserver/caddy/v2 v2.9.1
5+
require (
6+
github.com/caddyserver/caddy/v2 v2.9.1
7+
modernc.org/sqlite v1.37.1
8+
)

frameworks/caddy/handler.go

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package httparenahandler
22

33
import (
4+
"database/sql"
45
"encoding/json"
56
"fmt"
67
"hash/crc32"
@@ -9,13 +10,15 @@ import (
910
"net/http"
1011
"os"
1112
"path/filepath"
13+
"runtime"
1214
"strconv"
1315
"strings"
1416

1517
"github.com/caddyserver/caddy/v2"
1618
"github.com/caddyserver/caddy/v2/caddyconfig/caddyfile"
1719
"github.com/caddyserver/caddy/v2/caddyconfig/httpcaddyfile"
1820
"github.com/caddyserver/caddy/v2/modules/caddyhttp"
21+
_ "modernc.org/sqlite"
1922
)
2023

2124
func init() {
@@ -54,6 +57,7 @@ type Handler struct {
5457
jsonResponse []byte
5558
jsonLargeResponse []byte
5659
staticFiles map[string]staticFile
60+
db *sql.DB
5761
}
5862

5963
func (Handler) CaddyModule() caddy.ModuleInfo {
@@ -149,6 +153,13 @@ func (h *Handler) Provision(ctx caddy.Context) error {
149153
}
150154
}
151155

156+
// Open SQLite database
157+
db, err := sql.Open("sqlite", "file:/data/benchmark.db?mode=ro&immutable=1")
158+
if err == nil {
159+
db.SetMaxOpenConns(runtime.NumCPU())
160+
h.db = db
161+
}
162+
152163
return nil
153164
}
154165

@@ -226,6 +237,57 @@ func (h *Handler) ServeHTTP(w http.ResponseWriter, r *http.Request, next caddyht
226237
http.Error(w, "No dataset", 500)
227238
}
228239
return nil
240+
241+
case "/db":
242+
if h.db == nil {
243+
http.Error(w, "DB not available", 500)
244+
return nil
245+
}
246+
minStr := r.URL.Query().Get("min")
247+
maxStr := r.URL.Query().Get("max")
248+
minPrice := 10.0
249+
maxPrice := 50.0
250+
if v, err := strconv.ParseFloat(minStr, 64); err == nil {
251+
minPrice = v
252+
}
253+
if v, err := strconv.ParseFloat(maxStr, 64); err == nil {
254+
maxPrice = v
255+
}
256+
rows, err := h.db.Query("SELECT id, name, category, price, quantity, active, tags, rating_score, rating_count FROM items WHERE price BETWEEN ? AND ? LIMIT 50", minPrice, maxPrice)
257+
if err != nil {
258+
http.Error(w, "Query failed", 500)
259+
return nil
260+
}
261+
defer rows.Close()
262+
var items []map[string]interface{}
263+
for rows.Next() {
264+
var dbId int
265+
var name, category, tags string
266+
var price float64
267+
var quantity int
268+
var active int
269+
var ratingScore float64
270+
var ratingCount int
271+
if err := rows.Scan(&dbId, &name, &category, &price, &quantity, &active, &tags, &ratingScore, &ratingCount); err != nil {
272+
continue
273+
}
274+
var tagsArr []string
275+
json.Unmarshal([]byte(tags), &tagsArr)
276+
items = append(items, map[string]interface{}{
277+
"id": dbId, "name": name, "category": category,
278+
"price": price, "quantity": quantity, "active": active == 1,
279+
"tags": tagsArr,
280+
"rating": map[string]interface{}{"score": ratingScore, "count": ratingCount},
281+
})
282+
}
283+
resp := map[string]interface{}{
284+
"items": items,
285+
"count": len(items),
286+
}
287+
w.Header().Set("Content-Type", "application/json")
288+
w.Header().Set("Server", "caddy")
289+
json.NewEncoder(w).Encode(resp)
290+
return nil
229291
}
230292

231293
if strings.HasPrefix(path, "/static/") {

frameworks/caddy/meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
"compression",
1414
"upload",
1515
"noisy",
16+
"mixed",
1617
"baseline-h2",
1718
"static-h2",
1819
"baseline-h3",

frameworks/h2o/CMakeLists.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@ add_compile_definitions(H2O_USE_LIBUV=0)
66
set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -O3")
77
find_library(H2O_LIB h2o-evloop REQUIRED)
88
find_library(YAJL_LIB yajl REQUIRED)
9+
find_library(SQLITE3_LIB sqlite3 REQUIRED)
910
add_executable(h2o-app src/main.c)
1011
find_library(BROTLI_ENC brotlienc)
1112
find_library(BROTLI_DEC brotlidec)
1213
find_library(BROTLI_COMMON brotlicommon)
13-
target_link_libraries(h2o-app ${H2O_LIB} ssl crypto ${YAJL_LIB} z ${BROTLI_ENC} ${BROTLI_DEC} ${BROTLI_COMMON} pthread m)
14+
target_link_libraries(h2o-app ${H2O_LIB} ssl crypto ${YAJL_LIB} ${SQLITE3_LIB} z ${BROTLI_ENC} ${BROTLI_DEC} ${BROTLI_COMMON} pthread m)

0 commit comments

Comments
 (0)