Commit 5b0ba8d
rpc: compression with libdeflate (#20665)
close #17112
This PR replaces the existing single-path compress/gzip middleware in
node/rpcstack.go with a dual-path implementation that distinguishes
between streaming and non-streaming responses.
a) Non-streaming responses (standard JSON-RPC calls such as
eth_getBlockByNumber):
- are now compressed in one shot using go-libdeflate, a lightweight CGo
wrapper around ebiggers/libdeflate. Benchmarks show ~1.75x speedup vs
stdlib gzip on ~30 KB JSON payloads (4.6 ms vs 8.0 ms, 122 MB/s vs 70
MB/s); under high concurrency the advantage is larger due to lower CPU
usage per request.
- Since the compressed size is known before writing, Content-Length is
now set to the exact compressed size, avoiding unnecessary
Transfer-Encoding: chunked.
- Responses smaller than 1 KB are sent uncompressed: at that size the
CPU overhead of initialising the compressor outweighs the benefit, and
for very small payloads the compressed output can exceed the input size
due to gzip framing overhead.
b) Streaming responses (e.g. debug_traceTransaction, trace_filter) are
detected via http.Flusher: when the RPC handler calls Flush() before
writing, the middleware switches to stdlib compress/gzip in streaming
mode, compressing trace data incrementally without buffering the full
response.
Changes:
- node/rpcstack.go: new gzipResponseWriter with buffer/stream dual mode;
4 sync.Pool instances for zero-allocation hot path
- rpc/http.go: injects http.Flusher into request context via
httpFlusherContextKey
- rpc/handler.go: streaming methods call flush before writing to
activate streaming mode
- go.mod: adds github.com/erigontech/go-libdeflate v0.1.0
# 🚀 Performance Benchmarks: Gzip Optimization
---
<details>
<summary><b>1. Isolated Compression Benchmarks (libdeflate vs
stdlib)</b></summary>
Diff
Benchmark (Gzip isolation) Latency Throughput Mem Alloc
- BenchmarkStdlibGzip 8.0ms/req 70 MB/s 66KB
+ BenchmarkLibdeflateGzip 4.6ms/req 122 MB/s 63KB (2x faster)
Note: We observed a ~1.75x speedup on a single thread. Under high
concurrency, the advantage is even greater due to reduced CPU overhead.
</details>
<details>
<summary><b>2. eth_getBlockByNumber with txs (Old SW vs Main
SW)</b></summary>
Old SW - Results with instability and errors:
Diff
- [2. 1] qps: 2000 -> [R=97.74% max=9.103s error=503 Service
Unavailable]
- [3. 3] qps: 2300 -> [R=98.50% max=5.841s error=503 Service
Unavailable]
- [3. 4] qps: 2300 -> [R=99.80% max=5.634s error=503 Service
Unavailable]
- [3. 5] qps: 2300 -> [R=98.25% max=5.877s error=503 Service
Unavailable]
Main SW - Stable results with 100% success rate:
Diff
+ [2. 1] qps: 2000 -> [R=100.00% max=141.22ms]
+ [2. 5] qps: 2000 -> [R=100.00% max=157.7ms]
+ [3. 1] qps: 2300 -> [R=100.00% max=217.23ms]
+ [3. 5] qps: 2300 -> [R=100.00% max=224.174ms]
</details>
<details>
<summary><b>3. trace_block </b></summary>
| Metric | Old SW | Main SW | Speedup |
| :--- | :--- | :--- | :--- |
| **Throughput** | 375.9 r/s | **455.0 r/s** | **+21%** |
| **p50 Latency** | 114.4 ms | **96.9 ms** | **1.18x** |
| **p90 Latency** | 232.0 ms | **181.2 ms** | **1.28x** |
| **Mean Latency** | 132.4 ms | **109.5 ms** | **1.21x** |
</details>
<details>
<summary><b>4. Executes all RPC using http, http-compressed and
websockets</b></summary>
./run_all.sh -T http,http_comp,websocket
Run tests in parallel on localhost:8545/localhost:8551
Result directory:
/home/simon/silkworm/tests/rpc-tests3/integration/results
Time: 2026-04-19 08:58:05.257624
Total round_trip time: 3:40:01.359044
Total marshalling time: 0:00:00.063308
Total unmarshalling time: 0:01:40.509521
No of json Diffs: 0
Test time-elapsed: 0:08:37.467460
Available tests: 1436
Available tested api: 112
Number of loop: 1
Number of executed tests: 4152
Number of NOT executed tests: 156
Number of success tests: 4152
Number of failed tests: 0
</details>
---------
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>1 parent d7b2a63 commit 5b0ba8d
6 files changed
Lines changed: 409 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
6 | 6 | | |
7 | 7 | | |
8 | 8 | | |
| 9 | + | |
9 | 10 | | |
10 | 11 | | |
11 | 12 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
344 | 344 | | |
345 | 345 | | |
346 | 346 | | |
| 347 | + | |
| 348 | + | |
347 | 349 | | |
348 | 350 | | |
349 | 351 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
20 | 20 | | |
21 | 21 | | |
22 | 22 | | |
| 23 | + | |
23 | 24 | | |
24 | 25 | | |
25 | 26 | | |
| |||
28 | 29 | | |
29 | 30 | | |
30 | 31 | | |
| 32 | + | |
31 | 33 | | |
32 | 34 | | |
33 | 35 | | |
34 | 36 | | |
| 37 | + | |
| 38 | + | |
35 | 39 | | |
36 | 40 | | |
37 | 41 | | |
| |||
508 | 512 | | |
509 | 513 | | |
510 | 514 | | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
| 518 | + | |
| 519 | + | |
| 520 | + | |
| 521 | + | |
511 | 522 | | |
| 523 | + | |
| 524 | + | |
| 525 | + | |
| 526 | + | |
| 527 | + | |
| 528 | + | |
| 529 | + | |
| 530 | + | |
512 | 531 | | |
513 | | - | |
514 | | - | |
| 532 | + | |
| 533 | + | |
| 534 | + | |
| 535 | + | |
| 536 | + | |
| 537 | + | |
| 538 | + | |
| 539 | + | |
| 540 | + | |
515 | 541 | | |
516 | 542 | | |
517 | 543 | | |
| 544 | + | |
| 545 | + | |
| 546 | + | |
| 547 | + | |
| 548 | + | |
| 549 | + | |
| 550 | + | |
| 551 | + | |
| 552 | + | |
| 553 | + | |
| 554 | + | |
| 555 | + | |
| 556 | + | |
| 557 | + | |
| 558 | + | |
| 559 | + | |
| 560 | + | |
| 561 | + | |
| 562 | + | |
| 563 | + | |
| 564 | + | |
| 565 | + | |
| 566 | + | |
| 567 | + | |
| 568 | + | |
| 569 | + | |
| 570 | + | |
| 571 | + | |
| 572 | + | |
| 573 | + | |
| 574 | + | |
| 575 | + | |
| 576 | + | |
518 | 577 | | |
519 | | - | |
| 578 | + | |
| 579 | + | |
| 580 | + | |
520 | 581 | | |
521 | 582 | | |
522 | 583 | | |
523 | 584 | | |
524 | | - | |
525 | | - | |
| 585 | + | |
| 586 | + | |
| 587 | + | |
| 588 | + | |
| 589 | + | |
526 | 590 | | |
527 | 591 | | |
528 | 592 | | |
529 | | - | |
| 593 | + | |
| 594 | + | |
| 595 | + | |
| 596 | + | |
| 597 | + | |
| 598 | + | |
| 599 | + | |
| 600 | + | |
| 601 | + | |
| 602 | + | |
| 603 | + | |
| 604 | + | |
| 605 | + | |
| 606 | + | |
| 607 | + | |
| 608 | + | |
| 609 | + | |
| 610 | + | |
| 611 | + | |
| 612 | + | |
| 613 | + | |
| 614 | + | |
| 615 | + | |
| 616 | + | |
| 617 | + | |
| 618 | + | |
| 619 | + | |
| 620 | + | |
| 621 | + | |
| 622 | + | |
| 623 | + | |
| 624 | + | |
| 625 | + | |
| 626 | + | |
| 627 | + | |
| 628 | + | |
| 629 | + | |
| 630 | + | |
| 631 | + | |
| 632 | + | |
| 633 | + | |
| 634 | + | |
| 635 | + | |
| 636 | + | |
| 637 | + | |
| 638 | + | |
| 639 | + | |
| 640 | + | |
| 641 | + | |
| 642 | + | |
| 643 | + | |
| 644 | + | |
| 645 | + | |
| 646 | + | |
| 647 | + | |
| 648 | + | |
| 649 | + | |
| 650 | + | |
| 651 | + | |
| 652 | + | |
| 653 | + | |
| 654 | + | |
| 655 | + | |
| 656 | + | |
| 657 | + | |
| 658 | + | |
| 659 | + | |
| 660 | + | |
| 661 | + | |
| 662 | + | |
| 663 | + | |
| 664 | + | |
| 665 | + | |
| 666 | + | |
| 667 | + | |
| 668 | + | |
| 669 | + | |
| 670 | + | |
| 671 | + | |
| 672 | + | |
| 673 | + | |
| 674 | + | |
| 675 | + | |
| 676 | + | |
| 677 | + | |
| 678 | + | |
| 679 | + | |
| 680 | + | |
| 681 | + | |
| 682 | + | |
| 683 | + | |
| 684 | + | |
| 685 | + | |
| 686 | + | |
| 687 | + | |
| 688 | + | |
| 689 | + | |
530 | 690 | | |
531 | 691 | | |
532 | 692 | | |
| |||
536 | 696 | | |
537 | 697 | | |
538 | 698 | | |
539 | | - | |
540 | | - | |
541 | | - | |
542 | | - | |
543 | | - | |
544 | | - | |
545 | | - | |
546 | | - | |
547 | | - | |
| 699 | + | |
| 700 | + | |
| 701 | + | |
| 702 | + | |
| 703 | + | |
| 704 | + | |
548 | 705 | | |
549 | 706 | | |
550 | 707 | | |
| |||
0 commit comments