Skip to content

fasthttp: pin V to latest + cut per-request allocation (default GC)#918

Draft
enghitalo wants to merge 2 commits into
MDA2AV:mainfrom
enghitalo:chore/fasthttp-pin-latest-v
Draft

fasthttp: pin V to latest + cut per-request allocation (default GC)#918
enghitalo wants to merge 2 commits into
MDA2AV:mainfrom
enghitalo:chore/fasthttp-pin-latest-v

Conversation

@enghitalo

@enghitalo enghitalo commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Pin the V toolchain used by frameworks/fasthttp from c0624b274 to the latest upstream V master commit 6c4d26f1f for reproducible and up-to-date benchmark builds.

Why this can improve benchmark results

This update pulls in recent upstream V changes that are directly relevant to runtime behavior under load:

Closed issue references

Scope

  • Updated only: frameworks/fasthttp/Dockerfile

Update: also reduce per-request allocation (default GC, no -gc none)

Following the GC study (V_GC_TLA_STUDY.md), fasthttp's json path is
GC-collection-bound, so fewer per-request allocations = less Boehm stop-the-world =
more throughput, with bounded memory. Three output-identical changes:

  • content_owned: true on every response → the backend takes the response builder's
    buffer instead of cloning it (take_or_clone_content), removing one alloc per response.
  • zero-copy routing: method/target/route are tos() views into the request buffer
    instead of bytestr() / all_before() copies.
  • parse_u_at for the /json/{count} segment instead of route[6..].i64() (no substring).

Functionally validated end-to-end against Postgres (pipeline / baseline / json / async-db
/ upload). No -gc none.

@enghitalo

Copy link
Copy Markdown
Contributor Author

/benchmark -f fasthttp

@github-actions

Copy link
Copy Markdown
Contributor

👋 /benchmark request received. A collaborator will review and approve the run.

@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: fasthttp | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
pipelined 512 227,539 1157.9% 294MiB -9.8% +38.0%
pipelined 4096 229,683 1086.2% 315MiB -9.5% +33.5%
json 4096 79,554 2072.6% 306MiB -36.7% +23.9%
async-db 1024 10,086 5414.7% 507MiB +3.5% +110.4%
Full log
[run 1/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   54.99ms   49.60ms   96.40ms   192.10ms   274.00ms

  370311 requests in 5.00s, 369514 responses
  Throughput: 73.88K req/s
  Bandwidth:  255.49MB/s
  Status codes: 2xx=369514, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 369514 / 369514 responses (100.0%)
  Reconnects: 12857
  Per-template: 52550,53096,53128,52858,52897,52581,52404
  Per-template-ok: 52550,53096,53128,52858,52897,52581,52404
[info] CPU 1610.0% | Mem 304MiB

[run 2/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   51.22ms   49.20ms   89.60ms   133.30ms   181.00ms

  397898 requests in 5.00s, 397770 responses
  Throughput: 79.52K req/s
  Bandwidth:  275.09MB/s
  Status codes: 2xx=397770, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 397770 / 397770 responses (100.0%)
  Reconnects: 14102
  Per-template: 56884,56895,57133,56823,56885,56559,56591
  Per-template-ok: 56884,56895,57133,56823,56885,56559,56591
[info] CPU 2072.6% | Mem 306MiB

[run 3/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   51.09ms   49.30ms   90.70ms   134.00ms   183.50ms

  399396 requests in 5.00s, 397668 responses
  Throughput: 79.50K req/s
  Bandwidth:  275.23MB/s
  Status codes: 2xx=397668, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 397668 / 397668 responses (100.0%)
  Reconnects: 14087
  Per-template: 57117,56913,56372,57008,56992,56578,56688
  Per-template-ok: 57117,56913,56372,57008,56992,56578,56688
[info] CPU 1934.5% | Mem 305MiB

=== Best: 79554 req/s (CPU: 2072.6%, Mem: 306MiB) ===
[info] input BW: 3.79MB/s (avg template: 50 bytes)
[info] saved results/json/4096/fasthttp.json
httparena-bench-fasthttp
httparena-bench-fasthttp
[info] skip: fasthttp does not subscribe to json-comp
[info] skip: fasthttp does not subscribe to json-tls
[info] skip: fasthttp does not subscribe to upload
[info] skip: fasthttp does not subscribe to api-4
[info] skip: fasthttp does not subscribe to api-16
[info] skip: fasthttp does not subscribe to static

==============================================
=== fasthttp / async-db / 1024c (tool=gcannon) ===
==============================================
[info] waiting for server...
[info] server ready

[run 1/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   106.12ms   82.60ms   234.70ms   389.50ms   545.20ms

  96162 requests in 10.00s, 96162 responses
  Throughput: 9.61K req/s
  Bandwidth:  36.86MB/s
  Status codes: 2xx=96162, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 96162 / 96162 responses (100.0%)
  Reconnects: 3381
  Per-template: 18420,19225,19945,19688,18884
  Per-template-ok: 18420,19225,19945,19688,18884
[info] CPU 4565.2% | Mem 449MiB

[run 2/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   100.98ms   84.90ms   205.90ms   360.20ms   513.50ms

  100807 requests in 10.00s, 100807 responses
  Throughput: 10.08K req/s
  Bandwidth:  38.69MB/s
  Status codes: 2xx=100807, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 100807 / 100807 responses (100.0%)
  Reconnects: 3612
  Per-template: 19591,20123,20521,20445,20127
  Per-template-ok: 19591,20123,20521,20445,20127
[info] CPU 5131.6% | Mem 507MiB

[run 3/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   100.87ms   84.30ms   210.80ms   335.90ms   506.80ms

  100868 requests in 10.00s, 100868 responses
  Throughput: 10.08K req/s
  Bandwidth:  39.01MB/s
  Status codes: 2xx=100868, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 100868 / 100868 responses (100.0%)
  Reconnects: 3610
  Per-template: 19372,19883,20406,20768,20439
  Per-template-ok: 19372,19883,20406,20768,20439
[info] CPU 5414.7% | Mem 507MiB

=== Best: 10086 req/s (CPU: 5414.7%, Mem: 507MiB) ===
[info] input BW: 689.47KB/s (avg template: 70 bytes)
[info] saved results/async-db/1024/fasthttp.json
httparena-bench-fasthttp
httparena-bench-fasthttp
[info] skip: fasthttp does not subscribe to crud
[info] skip: fasthttp does not subscribe to fortunes
[info] skip: fasthttp does not subscribe to baseline-h2
[info] skip: fasthttp does not subscribe to static-h2
[info] skip: fasthttp does not subscribe to baseline-h2c
[info] skip: fasthttp does not subscribe to json-h2c
[info] skip: fasthttp does not subscribe to baseline-h3
[info] skip: fasthttp does not subscribe to static-h3
[info] skip: fasthttp does not subscribe to gateway-64
[info] skip: fasthttp does not subscribe to gateway-h3
[info] skip: fasthttp does not subscribe to production-stack
[info] skip: fasthttp does not subscribe to unary-grpc
[info] skip: fasthttp does not subscribe to unary-grpc-tls
[info] skip: fasthttp does not subscribe to stream-grpc
[info] skip: fasthttp does not subscribe to stream-grpc-tls
[info] skip: fasthttp does not subscribe to echo-ws
[info] skip: fasthttp does not subscribe to echo-ws-pipeline
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/async-db-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
[info] restoring loopback MTU to 65536

@enghitalo enghitalo marked this pull request as draft June 23, 2026 20:07
The study (V_GC_TLA_STUDY.md) showed fasthttp's json path is GC-collection-bound, so
fewer per-request allocations = less Boehm STW = more throughput, with bounded memory.
Three output-identical changes:
- content_owned: true on every response → the backend takes the builder buffer instead
  of cloning it (take_or_clone_content), removing one alloc per response.
- zero-copy routing: method/target/route as tos() views into the request buffer instead
  of bytestr()/all_before() copies.
- parse_u_at for the /json/{count} segment instead of route[6..].i64() (no substring).
Functionally validated end-to-end against Postgres (pipeline/baseline/json/async-db/upload).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@enghitalo

Copy link
Copy Markdown
Contributor Author

/benchmark -f fasthttp

@github-actions

Copy link
Copy Markdown
Contributor

👋 /benchmark request received. A collaborator will review and approve the run.

@enghitalo enghitalo changed the title fasthttp: pin V toolchain to latest upstream commit fasthttp: pin V to latest + cut per-request allocation (default GC) Jun 24, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Benchmark Results

Framework: fasthttp | Test: all tests

Test Conn RPS CPU Mem Δ RPS Δ Mem
pipelined 512 237,938 1128.0% 291MiB -5.6% +36.6%
pipelined 4096 235,232 1098.3% 314MiB -7.3% +33.1%
json 4096 105,643 2085.7% 305MiB -16.0% +23.5%
async-db 1024 10,178 5351.4% 583MiB +4.4% +141.9%
Full log
[run 1/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   41.35ms   41.40ms   87.40ms   153.00ms   214.80ms

  492948 requests in 5.00s, 492954 responses
  Throughput: 98.56K req/s
  Bandwidth:  341.04MB/s
  Status codes: 2xx=492954, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 492954 / 492954 responses (100.0%)
  Reconnects: 17807
  Per-template: 70068,70652,70505,70821,70811,70283,69814
  Per-template-ok: 70068,70652,70505,70821,70811,70283,69814
[info] CPU 1753.2% | Mem 304MiB

[run 2/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   38.40ms   42.60ms   60.70ms   99.70ms   142.40ms

  528411 requests in 5.00s, 528219 responses
  Throughput: 105.61K req/s
  Bandwidth:  364.62MB/s
  Status codes: 2xx=528219, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 528219 / 528219 responses (100.0%)
  Reconnects: 19248
  Per-template: 75523,75831,75910,76020,75197,75007,74731
  Per-template-ok: 75523,75831,75910,76020,75197,75007,74731
[info] CPU 2085.7% | Mem 305MiB

[run 3/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     4096 (64/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 7
  Expected:  200
  Duration:  5s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   38.48ms   42.70ms   62.60ms   98.80ms   143.60ms

  528791 requests in 5.00s, 527191 responses
  Throughput: 105.40K req/s
  Bandwidth:  364.93MB/s
  Status codes: 2xx=527191, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 527185 / 527191 responses (100.0%)
  Reconnects: 19269
  Per-template: 74570,75229,76106,76133,75272,74774,75101
  Per-template-ok: 74570,75229,76106,76133,75272,74774,75101
[info] CPU 1969.3% | Mem 305MiB

=== Best: 105643 req/s (CPU: 2085.7%, Mem: 305MiB) ===
[info] input BW: 5.04MB/s (avg template: 50 bytes)
[info] saved results/json/4096/fasthttp.json
httparena-bench-fasthttp
httparena-bench-fasthttp
[info] skip: fasthttp does not subscribe to json-comp
[info] skip: fasthttp does not subscribe to json-tls
[info] skip: fasthttp does not subscribe to upload
[info] skip: fasthttp does not subscribe to api-4
[info] skip: fasthttp does not subscribe to api-16
[info] skip: fasthttp does not subscribe to static

==============================================
=== fasthttp / async-db / 1024c (tool=gcannon) ===
==============================================
[info] waiting for server...
[info] server ready

[run 1/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   104.75ms   84.20ms   226.00ms   412.80ms   590.30ms

  97393 requests in 10.00s, 97393 responses
  Throughput: 9.73K req/s
  Bandwidth:  37.44MB/s
  Status codes: 2xx=97393, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 97393 / 97393 responses (100.0%)
  Reconnects: 3403
  Per-template: 18863,19275,19869,20014,19372
  Per-template-ok: 18863,19275,19869,20014,19372
[info] CPU 4618.1% | Mem 449MiB

[run 2/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   100.52ms   82.20ms   214.40ms   347.00ms   525.80ms

  101125 requests in 10.00s, 101125 responses
  Throughput: 10.11K req/s
  Bandwidth:  38.87MB/s
  Status codes: 2xx=101125, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 101125 / 101125 responses (100.0%)
  Reconnects: 3634
  Per-template: 19335,20144,20859,20754,20033
  Per-template-ok: 19335,20144,20859,20754,20033
[info] CPU 5189.1% | Mem 560MiB

[run 3/3]
gcannon v0.5.3
  Target:    localhost:8080/
  Threads:   64
  Conns:     1024 (16/thread)
  Pipeline:  1
  Req/conn:  25
  Templates: 5
  Expected:  200
  Duration:  10s


  Thread Stats   Avg      p50      p90      p99    p99.9
    Latency   100.06ms   85.30ms   203.00ms   331.00ms   448.60ms

  101783 requests in 10.00s, 101783 responses
  Throughput: 10.18K req/s
  Bandwidth:  39.17MB/s
  Status codes: 2xx=101783, 3xx=0, 4xx=0, 5xx=0
  Latency samples: 101783 / 101783 responses (100.0%)
  Reconnects: 3671
  Per-template: 19589,20219,20822,20812,20341
  Per-template-ok: 19589,20219,20822,20812,20341
[info] CPU 5351.4% | Mem 583MiB

=== Best: 10178 req/s (CPU: 5351.4%, Mem: 583MiB) ===
[info] input BW: 695.76KB/s (avg template: 70 bytes)
[info] saved results/async-db/1024/fasthttp.json
httparena-bench-fasthttp
httparena-bench-fasthttp
[info] skip: fasthttp does not subscribe to crud
[info] skip: fasthttp does not subscribe to fortunes
[info] skip: fasthttp does not subscribe to baseline-h2
[info] skip: fasthttp does not subscribe to static-h2
[info] skip: fasthttp does not subscribe to baseline-h2c
[info] skip: fasthttp does not subscribe to json-h2c
[info] skip: fasthttp does not subscribe to baseline-h3
[info] skip: fasthttp does not subscribe to static-h3
[info] skip: fasthttp does not subscribe to gateway-64
[info] skip: fasthttp does not subscribe to gateway-h3
[info] skip: fasthttp does not subscribe to production-stack
[info] skip: fasthttp does not subscribe to unary-grpc
[info] skip: fasthttp does not subscribe to unary-grpc-tls
[info] skip: fasthttp does not subscribe to stream-grpc
[info] skip: fasthttp does not subscribe to stream-grpc-tls
[info] skip: fasthttp does not subscribe to echo-ws
[info] skip: fasthttp does not subscribe to echo-ws-pipeline
[info] rebuilding site/data/*.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/frameworks.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/async-db-1024.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/json-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-4096.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/pipelined-512.json
[updated] /home/diogo/actions-runner/_work/HttpArena/HttpArena/site/data/current.json
[info] done
httparena-postgres
[info] restoring loopback MTU to 65536

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.

Array single-element push (<<) 4-7x slower on master vs 0.5.1 (alloc, push_many, indexed-write unaffected)

1 participant