Releases: tsenart/trunks
trunks v0.2.0
What's new
Comprehensive code quality overhaul from a Jon Gjengset-style review — 14 issues fixed across the entire codebase, with a cleaner public API.
cargo install trunks-cli # or: brew upgrade tsenart/tap/trunksBreaking changes ⚠️
-
Attackfields are now private. Use the new builder API:// Before (0.1.x) let atk = Attack { name: "test".into(), client, pacer, targets, workers: 4, ... }; // After (0.2.0) let atk = Attack::builder("test", client, pacer, targets) .workers(4) .max_workers(16) .duration(Duration::from_secs(10)) .build();
Optional fields have sensible defaults (workers=num_cpus, timeout=30s, max_body=-1, redirects=10).
-
Codectrait removed.JsonCodec,CsvCodec,MsgpackCodecnow have inherent async methods. Removeuse trunks::Codecfrom imports — call.encode()/.decode()directly. -
TargetsandAttackare no longer generic overR.Targets<R>is now justTargets.Attack<C, P, R>is nowAttack<C, P>. For lazy targets, wrap the reader:Targets::Lazy(Box::new(target_reader)).
Improvements
- DNS: fully async resolution using
tokio::net::UdpSocket— no morespawn_blockingper query, no thread pool exhaustion under load - DNS: transaction ID validation prevents accepting spoofed responses
- Memory: response bodies stream chunk-by-chunk up to
max_bodybytes instead of buffering the entire response before truncating - Memory:
@body_pathfile reads are cached — read once, reused across all targets referencing the same file - Performance: status codes use
BTreeMap<u16, u64>instead of allocatingStringkeys per request - Performance: proxy CONNECT response uses 512-byte buffered reads instead of byte-by-byte syscalls
- Performance: codec encode/decode no longer boxes futures via
async_trait
Bug fixes
- Fixed panic when request count exceeds
u32::MAX— mean latency usedas u32truncation causing divide-by-zero - Fixed
Metrics::close()not being idempotent — second call destroyed percentile data - Fixed
duration_as_nanossilently wrapping durations > 584 years — now saturates tou64::MAX - Msgpack decoder rejects frames > 64MB before allocating (prevents OOM from malicious input)
Internal
- 90 tests covering all fixes
AGENTS.mdwith project guidelines, architecture, CI/release processREVIEW.mdtracking all 17 review issues and resolutions
trunks v0.1.1
🧪 Comprehensive Test Suite & Library Modules
This release adds 75 tests across 9 modules — taking the codebase from 2 tests to thorough coverage — and extracts three new public library modules from the CLI.
New Library Modules
Three modules that previously lived as inline code in the CLI are now part of the trunks library crate, making them available to anyone building on trunks:
trunks::lttb— Largest Triangle Three Buckets downsampling for efficient time-series visualizationtrunks::plot— Self-contained HTML latency scatter plots with LTTB downsampling, dark theme, log scale toggle, and multi-series supporttrunks::PrometheusMetrics— Prometheus exposition format renderer with per-label histograms, byte counters, and failure tracking
Test Coverage
75 tests across all core modules, covering both happy paths and edge cases:
| Module | Tests | What's covered |
|---|---|---|
| Pacers | 14 | ConstantPacer (pacing, behind/ahead, zero freq/per, rate), LinearPacer (hits, rate growth, pacing), SinePacer (invalid configs, rate oscillation, peak/trough) |
| Hit Codecs | 8 | JSON, CSV, MessagePack round-trips; headers; error fields; special characters; empty bodies |
| LTTB | 8 | Threshold edge cases; first/last preservation; correct output size; known downsampling verification |
| Metrics | 7 | Empty/single/multi-hit accumulation; status code bucketing; error deduplication; rate/throughput; byte means |
| Reporters | 7 | Text section presence; JSON serde round-trip; histogram bucketing; HDR percentile format; Go-style duration formatting; bucket string parsing |
| Prometheus | 6 | Empty render; single hit exposition; histogram bucket counting; failure labels; multi-label; cumulative buckets |
| Plot | 5 | Empty input error; HTML structure; multi-attack series; error labeler; custom titles |
| Targets | 8 | HTTP format (method+URL, headers, comments); JSON format; static round-robin cycling; empty/invalid errors |
| Resolver | 12 | Address normalization (IPv4, IPv6, brackets, ports); DNS query packet structure (A/AAAA); DNS response parsing with crafted packets; name compression |
Install
cargo install trunks-cliOr use as a library:
cargo add trunksPlatforms
Pre-compiled binaries for 7 targets:
| Platform | Architecture | File |
|---|---|---|
| Linux (glibc) | x86_64 | trunks_0.1.1_x86_64-unknown-linux-gnu.tar.gz |
| Linux (musl) | x86_64 | trunks_0.1.1_x86_64-unknown-linux-musl.tar.gz |
| Linux (glibc) | aarch64 | trunks_0.1.1_aarch64-unknown-linux-gnu.tar.gz |
| Linux (musl) | aarch64 | trunks_0.1.1_aarch64-unknown-linux-musl.tar.gz |
| macOS | x86_64 | trunks_0.1.1_x86_64-apple-darwin.tar.gz |
| macOS | aarch64 (Apple Silicon) | trunks_0.1.1_aarch64-apple-darwin.tar.gz |
| Windows | x86_64 | trunks_0.1.1_x86_64-pc-windows-msvc.zip |
Verify downloads with the SHA256SUMS file.
trunks v0.1.0
🎉 First Release
Trunks is a versatile HTTP load testing tool written in Rust — the son of Vegeta, reborn in Rust for maximum performance. It's over 90,000!
Highlights
⚡ Rust performance — zero-cost async I/O with Tokio and Hyper, designed to saturate targets without saturating itself
🎯 Avoids Coordinated Omission — clock-based pacing, not response-driven, so your latency measurements are honest
🔄 Vegeta compatible — drop-in replacement for vegeta's CLI, target formats, and JSON output encoding. Your existing pipelines just work.
📊 Rich reporting — text summaries, JSON, bucketed histograms, HDR percentile plots, and interactive HTML latency scatter plots with LTTB downsampling
🔧 Usable as a library — trunks is both a Rust crate and a CLI (trunks-cli)
Features
- Pacers: constant rate, linear ramp, sine wave
- Dynamic worker scaling — auto-spawns workers when the attack falls behind
- HTTP/2, h2c (HTTP/2 cleartext), TLS (rustls), mTLS
- Unix domain socket support
- Custom DNS resolution with configurable caching TTL
- HTTP/HTTPS proxy support with CONNECT tunneling
- Prometheus metrics exporter (
/metricsendpoint) - Three output encodings: JSON, CSV, MessagePack
- Graceful two-phase shutdown — Ctrl+C drains in-flight requests, second Ctrl+C force exits
- Redirect following with cross-origin credential stripping
Quick Start
# Install
cargo install trunks-cli
# Run a load test
echo "GET http://localhost:8080/" | trunks attack --name test --rate 100/1s --duration 10s | trunks reportPlatforms
Pre-compiled binaries for 7 targets:
| Platform | Architecture | File |
|---|---|---|
| Linux (glibc) | x86_64 | trunks_0.1.0_x86_64-unknown-linux-gnu.tar.gz |
| Linux (musl) | x86_64 | trunks_0.1.0_x86_64-unknown-linux-musl.tar.gz |
| Linux (glibc) | aarch64 | trunks_0.1.0_aarch64-unknown-linux-gnu.tar.gz |
| Linux (musl) | aarch64 | trunks_0.1.0_aarch64-unknown-linux-musl.tar.gz |
| macOS | x86_64 | trunks_0.1.0_x86_64-apple-darwin.tar.gz |
| macOS | aarch64 (Apple Silicon) | trunks_0.1.0_aarch64-apple-darwin.tar.gz |
| Windows | x86_64 | trunks_0.1.0_x86_64-pc-windows-msvc.zip |
Verify downloads with the SHA256SUMS file.