Skip to content

fix(fiber): use built-in compression middleware instead of manual gzip/deflate#222

Merged
MDA2AV merged 1 commit intomainfrom
fix/fiber-compression-middleware
Mar 28, 2026
Merged

fix(fiber): use built-in compression middleware instead of manual gzip/deflate#222
MDA2AV merged 1 commit intomainfrom
fix/fiber-compression-middleware

Conversation

@BennyFranciscus
Copy link
Copy Markdown
Collaborator

@BennyFranciscus BennyFranciscus commented Mar 28, 2026

Summary

Replaces the hand-rolled compress/flate and compress/gzip writers in the /compression handler with Fiber's built-in compress middleware.

What changed

  • Removed: Manual Accept-Encoding parsing, manual Content-Encoding header setting, direct flate.NewWriter / gzip.NewWriterLevel calls
  • Added: compress.New(compress.Config{Level: compress.LevelBestSpeed}) applied globally via app.Use()
  • Result: The /compression handler just sends the raw JSON payload. Fiber's middleware handles Accept-Encoding negotiation and compression transparently.

Why

As flagged in #221, the previous implementation bypassed Fiber's documented compression API. The benchmark should measure how Fiber handles compression, not how Go's stdlib compressors perform behind Fiber's router.

Impact on other endpoints

None — gcannon doesn't send Accept-Encoding headers by default, so baseline, json, upload, db, etc. won't be compressed. Only the compression test (which explicitly sends Accept-Encoding: gzip) will trigger compression.

Fixes #221

…p/deflate

Replace hand-rolled compress/flate and compress/gzip writers with Fiber's
built-in compress middleware (github.com/gofiber/fiber/v2/middleware/compress).

The middleware is applied globally with LevelBestSpeed. It handles
Accept-Encoding negotiation, Content-Encoding headers, and compression
automatically — the /compression handler just sends the raw payload and
lets the framework decide whether to compress based on client headers.

Other endpoints (baseline, json, etc.) won't be affected since wrk
doesn't send Accept-Encoding by default.

Fixes #221
@MDA2AV
Copy link
Copy Markdown
Owner

MDA2AV commented Mar 28, 2026

@BennyFranciscus we dont use wrk, it's gcannon btw

@BennyFranciscus
Copy link
Copy Markdown
Collaborator Author

Oh right, my bad — gcannon, not wrk. Brain was on autopilot there 😅 I'll fix the PR description. Point still stands though — gcannon doesn't send Accept-Encoding by default on the non-compression tests, so the middleware won't kick in for those endpoints.

@MDA2AV MDA2AV requested review from MDA2AV and removed request for MDA2AV March 28, 2026 12:47
@MDA2AV
Copy link
Copy Markdown
Owner

MDA2AV commented Mar 28, 2026

The intended way by the framework, if it supports middleware for it, use it, if not then use the other approach

@BennyFranciscus
Copy link
Copy Markdown
Collaborator Author

Yeah exactly, that's what this PR does — Fiber has compress.New() as a proper middleware so we just use that. Clean and idiomatic.

Anything else you want changed or is this good to go?

@MDA2AV
Copy link
Copy Markdown
Owner

MDA2AV commented Mar 28, 2026

/benchmark compression

@github-actions
Copy link
Copy Markdown
Contributor

🚀 Benchmark run triggered for fiber (profile: compression). Results will be posted here when done.

@github-actions
Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: fiber | Profile: compression

fiber / compression / 4096c (p=1, r=0, cpu=unlimited)
  Best: 13635 req/s (CPU: 9415.5%, Mem: 3.4GiB) ===

fiber / compression / 16384c (p=1, r=0, cpu=unlimited)
  Best: 11659 req/s (CPU: 8383.3%, Mem: 10.6GiB) ===
Full log
#4 transferring context: 2B done
#4 DONE 0.0s

#5 [internal] load build context
#5 DONE 0.0s

#6 [build 1/6] FROM docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191
#6 resolve docker.io/library/golang:1.24-alpine@sha256:8bee1901f1e530bfb4a7850aa7a479d17ae3a18beb6e09064ed54cfd245b7191 0.1s done
#6 DONE 0.1s

#7 [stage-1 1/2] FROM docker.io/library/alpine:3.19@sha256:6baf43584bcb78f2e5847d1de515f23499913ac9f12bdf834811a3145eb11ca1
#7 resolve docker.io/library/alpine:3.19@sha256:6baf43584bcb78f2e5847d1de515f23499913ac9f12bdf834811a3145eb11ca1 0.1s done
#7 DONE 0.1s

#5 [internal] load build context
#5 transferring context: 18.91kB done
#5 DONE 0.0s

#8 [build 4/6] RUN go mod download
#8 CACHED

#9 [build 5/6] COPY main.go ./
#9 CACHED

#10 [build 3/6] COPY go.mod go.sum ./
#10 CACHED

#11 [build 6/6] RUN CGO_ENABLED=0 go build -o server main.go
#11 CACHED

#12 [build 2/6] WORKDIR /app
#12 CACHED

#13 [stage-1 2/2] COPY --from=build /app/server /server
#13 CACHED

#14 exporting to image
#14 exporting layers done
#14 exporting manifest sha256:1d69bb47770890c8dae07d8083529500a9be53f09ad3773591b10e5046b29d4b done
#14 exporting config sha256:c4664124e9ca86eb16bdbcf6c489c2cbc3a13384ee0ee0a36b0f68766af45f0a done
#14 exporting attestation manifest sha256:12851ed1e09d64ccf385f54b7158036c7685f4fcfb5abf38cdf1dfeaa212686c
#14 exporting attestation manifest sha256:12851ed1e09d64ccf385f54b7158036c7685f4fcfb5abf38cdf1dfeaa212686c 0.1s done
#14 exporting manifest list sha256:52d03d3dc6948a539323600ed9fdae7d9bcab3b815cc16d3bb10b4353aebce52 0.0s done
#14 naming to docker.io/library/httparena-fiber:latest done
#14 unpacking to docker.io/library/httparena-fiber:latest
#14 unpacking to docker.io/library/httparena-fiber:latest 0.1s done
#14 DONE 0.3s

==============================================
=== fiber / compression / 4096c (p=1, r=0, cpu=unlimited) ===
==============================================
3eed24720f51979d1b912f82869ff21be9f56de29c24cb5135c43da52d5ebfee
[wait] Waiting for server...
[ready] Server is up

[run 1/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   287.65ms   263.40ms   374.80ms   553.60ms   657.80ms

  68435 requests in 5.00s, 68179 responses
  Throughput: 13.63K req/s
  Bandwidth:  2.70GB/s
  Status codes: 2xx=68179, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 68179 / 68179 responses (100.0%)
  CPU: 9415.5% | Mem: 3.4GiB

[run 2/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   349.39ms   351.80ms   383.20ms   499.80ms   545.20ms

  56396 requests in 5.00s, 56364 responses
  Throughput: 11.27K req/s
  Bandwidth:  2.23GB/s
  Status codes: 2xx=56364, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 56364 / 56364 responses (100.0%)
  CPU: 9153.9% | Mem: 2.4GiB

[run 3/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   347.58ms   350.00ms   381.80ms   483.60ms   541.50ms

  56744 requests in 5.00s, 56744 responses
  Throughput: 11.34K req/s
  Bandwidth:  2.25GB/s
  Status codes: 2xx=56744, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 56744 / 56744 responses (100.0%)
  CPU: 9233.7% | Mem: 2.4GiB

=== Best: 13635 req/s (CPU: 9415.5%, Mem: 3.4GiB) ===
  Input BW: 985.34KB/s (avg template: 74 bytes)
[dry-run] Results not saved (use --save to persist)
httparena-bench-fiber
httparena-bench-fiber

==============================================
=== fiber / compression / 16384c (p=1, r=0, cpu=unlimited) ===
==============================================
d442e66c1fed5a18d1a2def220f5c80ff92fb63c77784a1c49e6a084f142408e
[wait] Waiting for server...
[ready] Server is up

[run 1/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.23s    1.26s    2.05s    2.62s    2.73s

  74425 requests in 5.00s, 58297 responses
  Throughput: 11.65K req/s
  Bandwidth:  2.31GB/s
  Status codes: 2xx=58297, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 58297 / 58297 responses (100.0%)
  CPU: 8383.3% | Mem: 10.6GiB

[run 2/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.18s    1.34s    1.38s    1.87s    1.98s

  74425 requests in 5.00s, 58041 responses
  Throughput: 11.60K req/s
  Bandwidth:  2.30GB/s
  Status codes: 2xx=58041, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 58041 / 58041 responses (100.0%)
  CPU: 9343.4% | Mem: 12.7GiB

[run 3/3]
gcannon — io_uring HTTP load generator
  Target:    localhost:8080/
  Threads:   64
  Conns:     16384 (256/thread)
  Pipeline:  1
  Req/conn:  unlimited (keep-alive)
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency    1.23s    1.35s    1.47s    1.90s    1.95s

  71846 requests in 5.00s, 55462 responses
  Throughput: 11.09K req/s
  Bandwidth:  2.20GB/s
  Status codes: 2xx=55462, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 55462 / 55462 responses (100.0%)
  CPU: 8811.6% | Mem: 8.4GiB

=== Best: 11659 req/s (CPU: 8383.3%, Mem: 10.6GiB) ===
  Input BW: 842.54KB/s (avg template: 74 bytes)
[dry-run] Results not saved (use --save to persist)
httparena-bench-fiber
httparena-bench-fiber
[restore] Restoring CPU governor to performance...

@MDA2AV MDA2AV merged commit 2f8c78e into main Mar 28, 2026
5 of 8 checks passed
@BennyFranciscus
Copy link
Copy Markdown
Collaborator Author

Nice — 13.6K req/s at 4096c, holds up well at 16384c too (11.6K). The middleware approach is performing solidly. Memory does climb a bit at high concurrency (10.6GiB at 16K connections) but that's expected with that many goroutines managing compressed buffers.

Looks good to me. Happy with how this landed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Audit] fiber: /compression bypasses Fiber built-in compression middleware

3 participants