HttpArena
Knowledge BaseFrameworks

Static File Serving Benchmark (HTTP/1.1) — Implementation Guide

Must load files from disk on every request. No in-memory caching, no memory-mapped files, no pre-loaded file buffers. Compression must use the framework's standard middleware or built-in static file handler - no handmade compression code. Serving pre-compressed .br/.gz variants from disk is allowed, but only through a documented framework API (e.g. ASP.NET MapStaticAssets, nginx gzip_static / brotli_static, Caddy precompressed). No custom file-suffix lookup logic.
May cache files in memory at startup, use memory-mapped files, pre-rendered response headers, or any caching strategy. May serve pre-compressed files (.gz, .br) from disk via any mechanism. Free to use any compression approach.
No specific rules.
Configuration is free, including sendfile, open_file_cache, mmap and in-memory caching - serving files fast from a tuned cache is the job. Pre-compressed .br/.gz variants may be served through the server's own mechanism (nginx gzip_static / brotli_static, Caddy precompressed). Bodies must come from the mounted static directory; a handler that synthesizes them is not serving files.

Serves 20 static files of various types and sizes over HTTP/1.1, simulating a realistic page load with diverse file types and sizes.

Connections: 1,024, 4,096, 6,800

Workload

The load generator (wrk) requests 20 static files in a round-robin pattern using a Lua rotation script. All requests include Accept-Encoding: br;q=1, gzip;q=0.8.

  • CSS (5 files, 8–200 KB): reset.css, layout.css, theme.css, components.css, utilities.css
  • JavaScript (5 files, 12–300 KB): analytics.js, helpers.js, app.js, vendor.js, router.js
  • HTML (2 files, 55–120 KB): header.html, footer.html
  • Fonts (2 files, 18–22 KB): regular.woff2, bold.woff2
  • SVG (2 files, 15–70 KB): logo.svg, icon-sprite.svg
  • Images (3 files, 6–45 KB): hero.webp, thumb1.webp, thumb2.webp
  • JSON (1 file, 3 KB): manifest.json

Total payload: ~842 KB across 20 files (~743 KB compressible text + ~99 KB binary). Brotli-compressed total: ~219 KB.

Pre-compressed versions of all text files (.gz at level 9, .br at level 11) are available in the data/static/ directory alongside the originals.

Compression

All requests include Accept-Encoding: br;q=1, gzip;q=0.8, indicating the client prefers Brotli but accepts gzip.

Compression is optional. Frameworks that don't compress will serve files uncompressed - there is no penalty or validation failure. However, frameworks that do compress will benefit from reduced I/O, which naturally improves throughput.

  • Text files (CSS, JS, HTML, SVG, JSON): good candidates for compression (68–94% size reduction with brotli)
  • Binary files (woff2, webp): already compressed formats - servers should skip compression for these
  • Pre-compressed files: .gz and .br versions are available on disk. Frameworks that support serving pre-compressed files via a documented API (e.g. Nginx gzip_static/brotli_static, Caddy precompressed, ASP.NET MapStaticAssets) can serve these directly with zero CPU overhead - this is allowed for both production and tuned entries.

Production rule: compression must come from the framework's standard middleware, built-in static file handler, or its documented pre-compressed-file API. No handmade compression code, no custom suffix-lookup logic.

Tuned rule: free to use any approach - custom compression, manual .br/.gz lookup, etc.

What it measures

  • Static file serving throughput over HTTP/1.1
  • Content-Type handling for different file types
  • File serving strategy efficiency (disk I/O vs caching, depending on type)
  • Response efficiency with varied payload sizes
  • Compression efficiency (optional - reduces I/O at the cost of CPU)

Expected request/response

GET /static/reset.css HTTP/1.1
Host: localhost:8080
Accept-Encoding: br;q=1, gzip;q=0.8
HTTP/1.1 200 OK
Content-Type: text/css
Content-Encoding: br

(compressed file contents)

Or without compression:

HTTP/1.1 200 OK
Content-Type: text/css

(file contents)

Parameters

ParameterValue
Endpoint20 URIs under /static/*
Connections1,024, 4,096, 6,800
Pipeline1
Duration5s
Runs3 (best taken)
Load generatorwrk with Lua rotation script