httpress 0.6.0

A fast HTTP benchmarking tool built in Rust
Documentation

httpress

Crates.io Downloads Documentation CI License

a fast HTTP benchmarking library and CLI tool

demo

Contents

Features

  • High Performance - async rust with minimal overhead
  • Detailed Metrics - latency percentiles, throughput, status code breakdown
  • Flexible Stop Conditions - duration, request-count or infinite
  • Concurrent Workers - configure the number of concurrent connections
  • Library + CLI - use as a rust library or standalone tool
  • Flexible Rate Control - use fixed rates or dynamic rate functions
  • Custom Request Generation - generate requests dynamically per-worker
  • Hook System - inject custom logic before/after each request
  • Simple Builder API - easy to use, type-safe configuration

Performance

  • Benchmarks run against a local hyper echo server.
  • Environment: Intel Core i5-8350U, Arch Linux x86_64.

Scaling

Concurrency Throughput p50 p99
5 17,315 req/s 0.25 ms 0.57 ms
10 20,909 req/s 0.39 ms 1.10 ms
25 29,071 req/s 0.70 ms 1.64 ms
50 32,000 req/s 1.25 ms 2.90 ms
100 32,502 req/s 2.42 ms 6.03 ms

Comparison to other similar tools (concurrency=100, 10 s)

Tool Throughput p50 p99
httpress 32,502 req/s 2.42 ms 6.03 ms
wrk¹ 39,135 req/s 2.47 ms 5.42 ms
hey 27,182 req/s 3.50 ms 9.40 ms

Sample output

Target: http://localhost:3000 Get
Concurrency: 100
Stop condition: Duration(10s)

Starting benchmark with 100 workers...

--- Benchmark Complete ---
Requests:     325107 total, 325107 success, 0 errors
Duration:     10.00s
Throughput:   32502.23 req/s
Transferred:  0.62 MB

Latency:
  Min:    175us
  Max:    45.12ms
  Mean:   2.52ms
  p50:    2.42ms
  p90:    3.91ms
  p95:    4.43ms
  p99:    6.03ms

Status codes:
  200: 325107

Installation

As a CLI Tool

cargo install httpress

As a Library

Add to your Cargo.toml:

[dependencies]
httpress = "0.6"
tokio = { version = "1", features = ["full"] }

Quick Start

use httpress::{Benchmark, Result};
use std::time::Duration;

#[tokio::main]
async fn main() -> Result<()> {
    let results = Benchmark::builder()
        .url("http://localhost:3000")
        .concurrency(50)
        .duration(Duration::from_secs(10))
        .show_progress(true)
        .build()?
        .run()
        .await?;

    results.print();
    Ok(())
}

CLI Usage

Basic Examples

# Run benchmark with 100 concurrent connections for 30 seconds
httpress http://example.com -c 100 -d 30s

# Fixed number of requests with rate limiting
httpress http://example.com -n 10000 -r 1000

# POST request with headers and body
httpress http://example.com/api -m POST \
  -H "Content-Type: application/json" \
  -b '{"key": "value"}'

# Run until interrupted (Ctrl+C)
httpress http://example.com -c 50

Options

Flag Description Default
-n, --requests Total number of requests -
-d, --duration Test duration (e.g. 10s, 1m) -
-c, --concurrency Concurrent connections 10
-r, --rate Rate limit (req/s) -
-m, --method HTTP method GET
-H, --header HTTP header (repeatable) -
-b, --body Request body -
-t, --timeout Request timeout in seconds 30

Library Usage

Basic Benchmark

let results = Benchmark::builder()
    .url("http://localhost:3000")
    .concurrency(50)
    .requests(1000)
    .show_progress(true)
    .build()?
    .run()
    .await?;

Custom Request Generation

.request_fn(|ctx: RequestContext| {
    let user_id = ctx.request_number % 100;
    RequestConfig {
        url: format!("http://localhost:3000/user/{}", user_id),
        method: HttpMethod::Get,
        headers: HashMap::new(),
        body: None,
    }
})

Dynamic Rate Control

.rate_fn(|ctx: RateContext| {
    let progress = (ctx.elapsed.as_secs_f64() / 10.0).min(1.0);
    100.0 + (900.0 * progress)  // ramp from 100 to 1000 req/s
})

Hook System

Before-request

You can use these for circuit breakers or conditional execution:

.before_request(|ctx: BeforeRequestContext| {
    let failure_rate = ctx.failed_requests as f64 / ctx.total_requests.max(1) as f64;
    if failure_rate > 0.5 && ctx.total_requests > 100 {
        HookAction::Abort
    } else {
        HookAction::Continue
    }
})

After-request

You can use them to collect custom metrics or write retry logic:

.after_request(|ctx: AfterRequestContext| {
    if let Some(status) = ctx.status {
        if status >= 500 {
            return HookAction::Retry;
        }
    }
    HookAction::Continue
})
.max_retries(3)

For complete API documentation, see docs.rs/httpress.

Examples

The examples/ directory contains:

  • basic_benchmark.rs - basic benchmark example
  • custom_requests.rs - dynamic request generation using request_fn
  • rate_ramping.rs - advanced rate control using rate_fn
  • hooks_metrics.rs - custom metrics collection using hooks

Run examples with:

cargo run --example basic_benchmark