Repository navigation
cleanup: honest benchmarks, matching echo apps, fix baseline - #27
Conversation
…m defaults - README: replace "10-100x" claim with actual measured ~2x PPS improvement, remove multi-core pipeline section (experimental), fix stale --dpdk flag - echo app: rewrite to mirror plain-echo (65 lines vs 282), demonstrating the drop-in replacement story (only difference is the import line) - plain-echo: add signal handling and read timeout to match echo structure - perf-test-log: add Run #4 entry for topology simplification PR #26 - perf-tests: remove rust-dpdk-multicore from default configs (experimental) https://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco
Integration Test Failure (Run 23536907061)Branch: failure-summary.json{
"failed_step": "deploy_infrastructure",
"error": "Infrastructure deployment failed",
"exit_code": 2,
"timestamp": "2026-03-25T10:48:49.559120Z",
"sender_instance_id": "",
"receiver_instance_id": "",
"commit": "ac0e079b854b3e1bacaecb19d301e227a88cb442",
"run_url": "https://github.com/gspivey/dpdk-stdlib-rust/actions/runs/23536907061"
}```
### instance-0-user-data.log (5003 bytes, last 80 lines)Dependencies resolved. Dependencies resolved. [ 60.408931] cloud-init[1729]: === Using pre-built DPDK AMI === [ 55.589468] cloud-init[1737]: === Ensuring SSM agent is installed and running === total 84 |
❌ Integration Tests Failed (Run 23536907061)Branch: Test ResultsApplication Logs (last 20 lines)Full Application Logs (last 200 lines each)Network & PCI Stateinstance-0-network-interfaces.loginstance-1-network-interfaces.log
|
Integration Test Failure (Run 23537360123)Branch: failure-summary.json{
"failed_step": "deploy_infrastructure",
"error": "Infrastructure deployment failed",
"exit_code": 2,
"timestamp": "2026-03-25T10:59:55.600723Z",
"sender_instance_id": "",
"receiver_instance_id": "",
"commit": "b22f32d05377d2597b6b4b7d2344bf39bd3c8ccc",
"run_url": "https://github.com/gspivey/dpdk-stdlib-rust/actions/runs/23537360123"
}```
### instance-0-user-data.log (5003 bytes, last 80 lines)Dependencies resolved. Dependencies resolved. [ 9.046252] cloud-init[1719]: Cloud-init v. 22.2.2 running 'modules:final' at Wed, 25 Mar 2026 10:57:17 +0000. Up 8.98 seconds. Amazon Linux 2023.10.20260302 ip-10-0-1-97 login: [ 26.753396] cloud-init[1719]: Amazon Linux 2023 Kernel Livepatch repository 14 kB/s | 30 kB 00:02 Amazon Linux 2023.10.20260302 ip-10-0-1-82 login: [ 25.283735] cloud-init[1733]: Amazon Linux 2023 Kernel Livepatch repository 290 kB/s | 30 kB 00:00 total 84 |
❌ Integration Tests Failed (Run 23537360123)Branch: Test ResultsApplication Logs (last 20 lines)Full Application Logs (last 200 lines each)Network & PCI Stateinstance-0-network-interfaces.loginstance-1-network-interfaces.log
|
Integration Test Failure (Run 23538977178)Branch: failure-summary.json{
"failed_step": "deploy_infrastructure",
"error": "Infrastructure deployment failed",
"exit_code": 2,
"timestamp": "2026-03-25T11:43:11.728416Z",
"sender_instance_id": "",
"receiver_instance_id": "",
"commit": "b22f32d05377d2597b6b4b7d2344bf39bd3c8ccc",
"run_url": "https://github.com/gspivey/dpdk-stdlib-rust/actions/runs/23538977178"
}```
### instance-0-user-data.log (5003 bytes, last 80 lines)Dependencies resolved. Dependencies resolved. [ 63.619939] cloud-init[1735]: which unzip: /usr/bin/unzip [ 73.611211] cloud-init[1738]: Attempt 14: waiting for secondary ENI... total 92 |
❌ Integration Tests Failed (Run 23538977178)Branch: Test ResultsApplication Logs (last 20 lines)Full Application Logs (last 200 lines each)Network & PCI Stateinstance-0-network-interfaces.loginstance-1-network-interfaces.log
|
The previous commit made dpdk-udp a non-optional dependency of the echo app (no feature flag needed). The CDK stacks were still passing --features echo/dpdk which caused cargo build to fail on EC2 instances, breaking integration tests at deploy_infrastructure step. https://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco
[CI] Stage: DeployInfrastructure ready.
|
[CI] Stage: SummaryAll tests PASSED. ARP seeding: kernel /proc/net/arp (automatic)
|
✅ Integration Tests Passed (Run 23540263285)Branch: Test Results
Application Logs (last 20 lines)receiver-echo-server.log sender-echo-server.log sender-test-client.log receiver-test-client-iperf.log sender-test-client-iperf.log Full Application Logs (last 200 lines each)receiver-echo-server.logsender-echo-server.logsender-test-client.logreceiver-test-client-iperf.logsender-test-client-iperf.log
|
[CI] Stage: DeployInfrastructure ready.
|
PR #26 did have a full perf run (GH Actions 23522716883). Key findings: - rust-dpdk single-core matches native-dpdk at 700K/1400B (both 36% drop) - rust-dpdk-multicore 100% broken (--workers flag removed by simplification) - DPDK delivers ~2x throughput of kernel sockets at 64B/700K saturation https://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco
[Perf] Stage: DeployDeploying |
[CI] Stage: SummaryAll tests PASSED. ARP seeding: kernel /proc/net/arp (automatic)
|
✅ Integration Tests Passed (Run 23540263498)Branch: Test Results
Application Logs (last 20 lines)receiver-echo-server.log sender-echo-server.log sender-test-client.log receiver-test-client-iperf.log sender-test-client-iperf.log Full Application Logs (last 200 lines each)receiver-echo-server.logsender-echo-server.logsender-test-client.logreceiver-test-client-iperf.logsender-test-client-iperf.log
|
[Perf] Stage: Instances Ready
|
[Perf] Stage: TRex ConfigStarting TRex configuration (MAC discovery + NIC binding)... |
[Perf] Stage: TRex Config OK
|
[Perf] Stage: TRex StartedTRex server running. Beginning benchmarks... |
[Perf] DUT ReadyDUT instance |
[Perf] Stage: Benchmark (1/4)Running |
[Perf] Benchmark Diag:
|
[Perf] Benchmark Diag:
|
[Perf] Stage: Benchmark (2/4)Running |
[Perf] Benchmark Diag:
|
[Perf] Benchmark Diag:
|
[Perf] Stage: Benchmark (3/4)Running |
After making dpdk-udp non-optional in echo, the rust-stdlib perf config broke (RX: 1 pps) because echo now always uses dpdk_udp::UdpSocket which tries DPDK init even when the NIC is in kernel mode. - rust-stdlib now runs plain-echo (std::net) instead of echo - Remove rust-stdlib from default configs (redundant with plain-rust) - Default perf configs: plain-rust, rust-dpdk, native-dpdk https://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco
[Perf] Benchmark Diag:
|
[Perf] Stage: DeployDeploying |
[CI] Stage: DeployInfrastructure ready.
|
[Perf] Stage: Instances Ready
|
[Perf] Stage: TRex ConfigStarting TRex configuration (MAC discovery + NIC binding)... |
[Perf] Stage: TRex Config OK
|
[Perf] Stage: TRex StartedTRex server running. Beginning benchmarks... |
[Perf] DUT ReadyDUT instance |
[Perf] Stage: Benchmark (1/3)Running |
[Perf] Benchmark Diag:
|
[Perf] Benchmark Diag:
|
[Perf] Stage: Benchmark (2/3)Running |
[CI] Stage: SummaryAll tests PASSED. ARP seeding: kernel /proc/net/arp (automatic)
|
[Perf] Benchmark Diag:
|
✅ Integration Tests Passed (Run 23568847540)Branch: Test Results
Application Logs (last 20 lines)receiver-echo-server.log sender-echo-server.log sender-test-client.log receiver-test-client-iperf.log sender-test-client-iperf.log Full Application Logs (last 200 lines each)receiver-echo-server.logsender-echo-server.logsender-test-client.logreceiver-test-client-iperf.logsender-test-client-iperf.log
|
Run #5 (23548559577) had anomalous kernel numbers (78% drop at 64B/700K) due to a bad EC2 instance. Run #6 (23567309410) shows normal kernel performance (51% drop) consistent with Run #4. Updated both perf-test-log.md and README performance tables with the correct data. DPDK advantage is consistently ~2x at saturation, not the 3-4x that the outlier suggested. https://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco
[Perf] Benchmark Diag:
|
[Perf] Stage: Benchmark (3/3)Running |
[Perf] Benchmark Diag:
|
[CI] Stage: DeployInfrastructure ready.
|
[Perf] Benchmark Diag:
|
[Perf] Diag: testpmd logtestpmd output (last 30 lines) |
[Perf] Stage: Results[23:52:05] INFO Generating markdown summary... Performance Test Results — c5n.2xlargeCommit: 1400B packets
512B packets
64B packets
|
[CI] Stage: SummaryAll tests PASSED. ARP seeding: kernel /proc/net/arp (automatic)
|
✅ Integration Tests Passed (Run 23569743098)Branch: Test Results
Application Logs (last 20 lines)receiver-echo-server.log sender-echo-server.log sender-test-client.log receiver-test-client-iperf.log sender-test-client-iperf.log Full Application Logs (last 200 lines each)receiver-echo-server.logsender-echo-server.logsender-test-client.logreceiver-test-client-iperf.logsender-test-client-iperf.log
|
Performance test results from GH Actions run 26815657085: - rust-dpdk at 700K PPS 64B: 689,799 RX (1.46% drop) - native-dpdk at 700K PPS 64B: 688,347 RX (1.66% drop) - No regression vs Run #26 Synthetic CPU-only IPv6 vs IPv4 comparison confirms expected ~28% TX overhead at 64B due to larger headers and mandatory UDP checksum. RX performance equivalent. Marks IPv6 roadmap tasks 3 and 9 as complete.
Performance tests show no regression — TCP engine code has zero impact on UDP datapath. rust-dpdk results consistent with Run #27.
## ROADMAP Item `#27 dpdk-stdlib-tcp: Sync socket — engine loop and DpdkTcpStream` Spec: `.kiro/specs/tcp-support/` · tasks 8.1, 8.2, 8.3 ## Changes ### engine_loop (task 8.2) - Selects on `rx_readiness` | `engine_wakeup` | timer deadline - Dispatches: `parse_tcp_packet` → `on_segment`, `cmd_rx.try_recv()` → `on_command`, `on_tick(clock.now())` - Handles all three `RxReadiness` variants (Condvar/PollOnly/Fd) - Sends outbound frames via `backend.send_frame` ### connect_v4 + connect_timeout (task 8.1) - Resolves dst_mac via `NeighborResolver.resolve()` - Creates `ConnectionHandle` with SPSC rings - Sends `EngineCommand::Connect` with resolved MACs - Parks on oneshot until handshake completes or error - `connect_timeout` uses `recv_timeout` for bounded wait ### DpdkTcpStream (task 8.3) - `io::Read` with P0-B recheck-under-lock pattern (check error → try rx_ring.read → check eof → lock notify_lock → recheck → condvar.wait) - `io::Write` with push to tx_ring, signal engine_wakeup, block if full - Honors `set_nonblocking` (→ `WouldBlock`) and `read_timeout`/`write_timeout` (condvar.wait_timeout → `TimedOut`) - `Drop` → decrement app_refcount → send Close on last handle ### Supporting changes - Added `clock()` and `next_timer_deadline()` to `TcpEngine` - Added `wakeup()` accessor to `CommandSender` ## Tests Added 12 new unit tests covering: - Nonblocking read/write (WouldBlock) - Data delivery from rx_ring - EOF flag detection - Sticky error propagation - Write pushes to tx_ring - Read timeout expiry - Blocking read wakes on data (threaded) - Drop sends Close command - connect_v4 resolves MAC and sends command - connect_timeout returns TimedOut ## Validation - `cargo build && cargo test`: all 1007 workspace tests pass - Zero warnings in new code (only pre-existing warnings in upstream dpdk-stdlib) --------- Co-authored-by: Agent Router <agent@agent-router.dev>
Summary
dpdk_udp::UdpSocketvsstd::net::UdpSocket), demonstrating the drop-in replacement storyrust-stdlibperf config was running our abstraction layer in kernel-fallback mode, not cleanstd::net. Now usesplain-echofor honest comparisonBenchmark Results (Run #6 — 23567309410)
At 350K PPS, DPDK delivers near-zero drops across all packet sizes while kernel drops 6-19%.
Test plan
cargo build && cargo testpass locallyhttps://claude.ai/code/session_013kEK2d9wyTRWwmoAB4VBco