Add Scotty: Haskell web framework on Warp (first Haskell entry!)#233
Add Scotty: Haskell web framework on Warp (first Haskell entry!)#233BennyFranciscus wants to merge 3 commits intoMDA2AV:mainfrom
Conversation
Scotty is a lightweight Haskell web framework inspired by Ruby's Sinatra, built on top of the high-performance Warp HTTP server. - Language: Haskell (GHC 9.8, compiled with -O2 -threaded) - Engine: Warp - Tests: baseline, pipelined, noisy, limited-conn, json, upload, compression, mixed, async-db, static - All 29 validation checks pass Implementation notes: - Dataset and large payload pre-loaded into memory at startup - Static files cached in a Map at startup with correct MIME types - Manual gzip/deflate compression using zlib (level 1 for speed) - SQLite via sqlite-simple, PostgreSQL via postgresql-simple - Multi-stage Docker build with bookworm-slim runtime
|
/benchmark |
|
🚀 Benchmark run triggered for |
Benchmark ResultsFramework: Full log |
|
Benchmark results are in — nice! Baseline/JSON/Pipelined look solid: 11-15K req/s across concurrency levels. Not bad at all for Haskell, especially considering Scotty is a high-level framework on top of Warp. Upload is the problem: 51 req/s at 64c/256c, then drops to 0 req/s at 512c. Memory balloons to 24 GiB. Classic sign that Wai/Warp is buffering the entire 20MB upload body in memory before passing it to the handler. At 512 concurrent connections that's ~10GB of request bodies in flight, which likely OOMs or stalls the GHC runtime. I'll look into whether Scotty/Wai supports lazy or streaming request body consumption — if we can process chunks incrementally instead of |
…emory Upload was using Scotty's 'body' (strictRequestBody) which reads the entire request body into a lazy ByteString before processing. At 512 concurrent connections with 20MB payloads, this causes ~10GB memory pressure and OOMs the GHC runtime (0 req/s at 512c, 24GiB at 256c). Switch to streaming via Wai's getRequestBodyChunk — reads and counts bytes incrementally with constant memory overhead.
|
Pushed a fix — switched upload handler from This should fix the 0 req/s at 512c and the 24 GiB memory balloon. |
|
very low cpu usage |
|
Yeah, really bad CPU utilization — only ~270% out of 6400% available. GHC's IO manager with Going to try |
GHC's IO manager doesn't scale well past a few cores for network workloads — -N (all 64 cores) was only hitting ~270% CPU due to scheduler and lock contention. -N4 with -qn4 (4 parallel GC threads) should give better throughput by reducing overhead.
|
Pushed a fix — limited RTS to If throughput is still low after re-benchmark, could try |
|
@MDA2AV Could we get a re-benchmark when you get a chance? The |
Scotty
Adds Scotty — a lightweight Haskell web framework inspired by Ruby's Sinatra, running on the Warp HTTP server.
This is the first Haskell entry in HttpArena! 🎉
Details
Subscribed Tests
baseline, pipelined, noisy, limited-conn, json, upload, compression, mixed, async-db, static
Implementation Notes
-O2 -threaded -rtsoptsand runtime flags-N -A64m -I0for maximum throughputMapat startup with correct MIME typessqlite-simple, PostgreSQL viapostgresql-simple(connection-per-request with bracket)Validation
All 29 validation checks pass locally ✅
cc @scotty-web — would love to see Scotty's numbers on the leaderboard!
/validate