Skip to main content

A Python HTTP Client Performance Benchmark Framework

Project description

โšก HTTP Client & Server Performance Benchmark Framework

Python 3.12+ License: MIT


๐Ÿš€ Introduction

Stop guessing. Start measuring. ๐ŸŽฏ Engineering decisions should be backed by hard data, not hunches. Make data-driven choices for your HTTP stack with precision, high-concurrency benchmarking.

In the high-stakes world of performance-critical services, your choice of HTTP client, server infrastructure, and request handling isn't just a detailโ€”it's the backbone of your application's scalability. This framework eliminates the guesswork by providing comprehensive, real-world benchmarks across your entire HTTP ecosystem.

๐ŸŽฏ Why This Framework?

Most benchmarking tools focus on either just the client or just the server. We take a holistic, multi-dimensional approach to help you optimize the three critical pillars of your HTTP infrastructure:

๐Ÿ”ง 1. HTTP Client Selection โ€” Choose Your Weapon

Find the perfect library for your specific workload. Compare the battle-tested requests, the modern httpx, or the high-performance aiohttp and pycurl. Get the numbers, not the hype.

Available Arsenal:

  • ๐Ÿ requests โ€” The battle-tested industry standard
  • โšก httpx โ€” Modern, feature-rich HTTP/1.1 & HTTP/2 with sync/async flexibility
  • ๐ŸŒŠ aiohttp โ€” The high-performance async engine for non-blocking I/O
  • ๐Ÿ”— pycurl โ€” Blazing fast C-level bindings via libcurl
  • ๐Ÿš„ requestx โ€” Performance-tuned dual-mode execution
  • ๐Ÿ”Œ urllib3 โ€” Rock-solid connection pooling at the core

๐Ÿ—๏ธ 2. Server Infrastructure โ€” Build Your Battlefield

Don't test in a vacuum. Benchmark against production-grade environments. Compare how different reverse proxies and load balancers handle the heat.

Battlefield Scenarios:

  • ๐ŸŽˆ Simple HTTPBin โ€” Lightning-fast validation with a lightweight instance
  • ๐ŸŽช Traefik Load Balancer โ€” Modern, cloud-native proxying across triple backend instances
  • ๐Ÿš€ Nginx Load Balancer โ€” Battle-hardened, high-throughput reverse proxy simulation

๐Ÿ“ฎ 3. HTTP Methods โ€” Test What Matters

Performance isn't uniform. A GET request behaves differently than a heavy POST. Benchmark the exact operations your users actually perform with full support for the entire HTTP method specification.


๐Ÿ’Ž Key Features

โœ… Infinite Combinations โ€” Mix and match any client, server, and method for 360ยฐ coverage
โœ… Granular Telemetry โ€” Track throughput (RPS), p95/p99 latency, and real-time CPU/Memory usage
โœ… Long-term Analysis โ€” Built-in SQLite persistence for historical trend tracking and regression testing
โœ… Production Parity โ€” Fully supports HTTPS, load balancers, and multi-instance topologies
โœ… Stealth Monitoring โ€” Background resource sampling ensures zero interference with benchmark accuracy
โœ… Developer First โ€” Modular adapter pattern makes adding custom clients a breeze


๐ŸŽฌ Quick Example

Run a head-to-head comparison between top libraries using high-concurrency POST requests against an Nginx-backed cluster:

python -m http_benchmark.cli \
  --url https://localhost/post \
  --method POST \
  --body '{"test": "data"}' \
  --compare requests httpx aiohttp \
  --concurrency 5 \
  --duration 1

The Result? Cold, hard facts delivered straight to your console. End the architecture debates and start building on a foundation of measured performance.


๐Ÿ—บ๏ธ Architecture

The framework is built with extensibility in mind, featuring a clean adapter layer for HTTP clients, a non-blocking resource monitoring system, and a robust persistence layer.

System Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   CLI/API       โ”‚    โ”‚   HTTP Client   โ”‚    โ”‚   Test Server   โ”‚
โ”‚   Benchmark     โ”‚โ”€โ”€โ”€โ–ถโ”‚   (requests/    โ”‚โ”€โ”€โ”€โ–ถโ”‚   (httpbin/     โ”‚
โ”‚   Config        โ”‚    โ”‚    httpx/etc)   โ”‚    โ”‚    traefik/     โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ”‚    nginx)       โ”‚
                                 โ”‚            โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
                                 โ”‚                       โ”‚
                                 โ–ผ                       โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”    โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚   Console       โ”‚โ—€โ”€โ”€โ”€โ”€โ”‚   Results       โ”‚โ—€โ”€โ”€โ”€โ”€โ”‚   Performance   โ”‚
โ”‚   Output        โ”‚    โ”‚   Processing    โ”‚    โ”‚   Metrics       โ”‚
โ”‚                 โ”‚    โ”‚                 โ”‚    โ”‚   Collection    โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜    โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
          โ”‚                       โ”‚
          โ”‚                       โ–ผ
          โ”‚            โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
          โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถโ”‚   SQLite DB     โ”‚
                       โ”‚   Storage       โ”‚
                       โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Data Flow:

  1. Configure: Define client, server, method, and concurrency parameters.
  2. Execute: Launch high-frequency requests while monitoring system resources in the background.
  3. Analyze: Aggregate performance metrics including throughput and latency percentiles.
  4. Persist: Store detailed results in SQLite for historical analysis.
  5. Report: Visualize comparative data directly in your terminal.

๐Ÿš€ Installation

๐Ÿ“‹ Prerequisites

  • Python 3.12+
  • Docker & Docker Compose (for running isolated test servers)

๐Ÿ”ง Setup

  1. Clone the repository:

    git clone https://github.com/your-repo/http-client-benchmarker.git
    cd http-client-benchmarker
    
  2. Install dependencies using uv (recommended for speed):

    uv venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    uv pip install -e ".[dev]"
    

    Or using standard pip:

    python -m venv .venv
    source .venv/bin/activate  # On Windows: .venv\Scripts\activate
    pip install -e ".[dev]"
    

โšก Quick Start

๐Ÿ–ฅ๏ธ Step 1: Launch Your Test Server

Choose a server configuration that mirrors your production environment:

# Option 1: Simple HTTPBin (single instance, HTTP only)
docker-compose -f httpbin_server/docker-compose.httpbin.yml up -d

# Option 2: Traefik Load Balancer (3 instances, HTTP/HTTPS, cloud-native)
docker-compose -f httpbin_server/docker-compose.traefik.yml up -d

# Option 3: Nginx Load Balancer (3 instances, HTTP/HTTPS, high performance)
docker-compose -f httpbin_server/docker-compose.nginx.yml up -d

๐Ÿ“Š Server Comparison Matrix

Feature ๐ŸŽˆ Simple HTTPBin ๐ŸŽช Traefik ๐Ÿš€ Nginx
Backend Instances 1 3 3
HTTP Support โœ… โœ… โœ…
HTTPS Support โŒ โœ… โœ…
Load Balancing โŒ โœ… โœ…
Resource Overhead Low High Medium
Best For Quick tests Real-world simulation Raw performance

โ–ถ๏ธ Step 2: Run Your Benchmark

๐Ÿ–ฅ๏ธ Using CLI

Single Client Benchmark:

python -m http_benchmark.cli \
  --url http://localhost/get \
  --client httpx \
  --concurrency 5 \
  --duration 2

Head-to-Head Comparison:

python -m http_benchmark.cli \
  --url http://localhost/get \
  --compare requests httpx aiohttp \
  --concurrency 5 \
  --duration 2

Different HTTP Methods:

# POST with payload
python -m http_benchmark.cli --url http://localhost/post --method POST --body '{"user": "test"}' --client httpx --concurrency 1 --duration 1

# PUT, PATCH, DELETE
python -m http_benchmark.cli --url http://localhost/put --method PUT --client aiohttp --concurrency 1 --duration 1

๐Ÿ Using Python Library

The framework can be used programmatically as a Python library for fine-grained control and integration into your own testing infrastructure.

Basic Usage:

from http_benchmark.benchmark import BenchmarkRunner
from http_benchmark.models.benchmark_configuration import BenchmarkConfiguration
from http_benchmark.storage import ResultStorage

# Configure your benchmark
config = BenchmarkConfiguration(
    target_url="http://localhost/get",
    http_method="GET",
    concurrency=10,
    duration_seconds=30,
    client_library="requests",
    is_async=False,
    verify_ssl=False,
    timeout=30,
)

# Run the benchmark
runner = BenchmarkRunner(config)
result = runner.run()

# Access results
print(f"RPS: {result.requests_per_second:.2f}")
print(f"Avg Latency: {result.avg_response_time * 1000:.2f}ms")
print(f"P95 Latency: {result.p95_response_time * 1000:.2f}ms")

# Persist results
storage = ResultStorage()
storage.save_result(result)

Compare Multiple Clients:

# Compare multiple HTTP clients
clients = ["requests", "httpx", "aiohttp", "urllib3", "pycurl", "requestx"]
results = {}

for client in clients:
    is_async = client in ("aiohttp", "requestx-async")
    actual_client = client.replace("-async", "")
    
    config = BenchmarkConfiguration(
        target_url="http://localhost/get",
        http_method="GET",
        concurrency=5,
        duration_seconds=10,
        client_library=actual_client,
        is_async=is_async,
    )
    
    runner = BenchmarkRunner(config)
    result = runner.run()
    results[client] = result
    
    print(f"{client}: {result.requests_per_second:.2f} RPS")

# Find the fastest
best = max(results.items(), key=lambda x: x[1].requests_per_second)
print(f"\nFastest: {best[0]} ({best[1].requests_per_second:.2f} RPS)")

Async Usage:

# For async clients (aiohttp, httpx with is_async=True)
config = BenchmarkConfiguration(
    target_url="http://localhost/get",
    http_method="GET",
    concurrency=100,
    duration_seconds=30,
    client_library="aiohttp",
    is_async=True,
)

runner = BenchmarkRunner(config)
result = runner.run()
print(f"Async RPS: {result.requests_per_second:.2f}")

๐ŸŽฏ Use Cases

๐Ÿ” Client Selection & Migration

Scenario: Your team is considering migrating from requests to httpx to leverage HTTP/2.
Solution: Run a 60-second high-concurrency comparison to quantify RPS, latency, and resource usage.

๐Ÿ“ˆ Method-Specific Optimization

Scenario: Your API's POST endpoints feel sluggish compared to GET requests.
Solution: Separately benchmark GET and POST methods with realistic payloads to identify the bottleneck.

๐Ÿ—๏ธ Infrastructure Comparison

Scenario: Choosing between Nginx and Traefik for your production load balancer.
Solution: Swap Docker Compose environments and run identical benchmark suites to see which proxy handles the load better.


๐Ÿ”ง Supported HTTP Clients

Library Sync Async Key Characteristics
aiohttp โŒ โœ… Non-blocking I/O, optimal for async services, built-in connection pooling
httpx โœ… โœ… HTTP/2 support, requests-compatible API, modern design
pycurl โœ… โŒ libcurl bindings, minimal overhead, C-level performance
requests โœ… โŒ Industry standard, extensive ecosystem, blocking I/O
requestx โœ… โœ… Performance-optimized fork, dual-mode execution
urllib3 โœ… โŒ Foundation library, thread-safe pooling, low-level control

๐Ÿ’พ Database Schema & Analysis

All benchmark results are persisted to SQLite for long-term trend analysis and data-driven decision making.

๐Ÿ“‹ Schema: benchmark_results

Field Type Description
id TEXT Primary key (UUID)
name TEXT Benchmark run identifier
client_library TEXT Library name (e.g., "httpx")
client_type TEXT Execution model ("sync" or "async")
http_method TEXT HTTP method (GET, POST, etc.)
url TEXT Target URL
start_time TEXT Start timestamp (ISO 8601)
end_time TEXT End timestamp (ISO 8601)
duration REAL Total execution time (seconds)
requests_count INTEGER Total requests completed
requests_per_second REAL Average throughput (RPS)
avg_response_time REAL Mean latency (seconds)
p95_response_time REAL 95th percentile latency (seconds)
p99_response_time REAL 99th percentile latency (seconds)
cpu_usage_avg REAL Average CPU usage (%)
memory_usage_avg REAL Average RSS memory (MB)
error_count INTEGER Total failed requests
error_rate REAL Failure percentage (0-100)
concurrency_level INTEGER Configured concurrency
config_snapshot TEXT JSON snapshot of full configuration
created_at TEXT Record creation timestamp (ISO 8601)

๐Ÿ” Analysis Examples

Compare Client Performance:

SELECT 
    client_library,
    ROUND(AVG(requests_per_second), 2) as avg_rps,
    ROUND(AVG(avg_response_time) * 1000, 2) as avg_latency_ms,
    ROUND(AVG(cpu_usage_avg), 2) as avg_cpu_pct
FROM benchmark_results
WHERE http_method = 'GET'
GROUP BY client_library
ORDER BY avg_rps DESC;

Track Performance Over Time:

SELECT 
    DATE(created_at) as benchmark_date,
    client_library,
    AVG(requests_per_second) as daily_avg_rps
FROM benchmark_results
WHERE client_library = 'httpx'
GROUP BY DATE(created_at), client_library
ORDER BY benchmark_date DESC;

๐Ÿงช Development

โœ… Running Tests

# Run all tests
python -m unittest discover tests

# Run specific suite
python -m unittest discover tests/unit
python -m unittest discover tests/integration
python -m unittest discover tests/performance

๐ŸŽจ Code Quality

# Format and lint
black http_benchmark/ tests/ --line-length 120
flake8 http_benchmark/ tests/ --max-line-length=120
mypy http_benchmark/

๐Ÿ”ง Adding a New HTTP Client

  1. Create a new adapter in http_benchmark/clients/ inheriting from BaseAdapter.
  2. Register the adapter in http_benchmark/benchmark.py within BenchmarkRunner.
  3. Add corresponding unit tests in tests/unit/.

๐Ÿ—๏ธ Architecture Deep Dive

๐Ÿ”Œ Adapter Pattern

The framework uses a clean adapter pattern to decouple the benchmarking engine from specific HTTP client implementations. Each adapter implements a unified interface, making it trivial to add new clients without modifying core logic.

๐Ÿ“Š Non-Blocking Resource Monitoring

A background thread continuously samples system metrics using psutil without interfering with benchmark execution. Metrics are collected at high frequency and aggregated post-benchmark.

โšก Concurrency Management

  • Synchronous Clients: Managed via ThreadPoolExecutor with optimized pool sizing.
  • Asynchronous Clients: Powered by asyncio with task-based concurrency for maximum efficiency.

๐Ÿค Contributing

We welcome contributions! Please feel free to submit a Pull Request.


๐Ÿ“„ License

This project is licensed under the MIT License. See LICENSE for details.


Ready to optimize your HTTP stack? Start benchmarking now! ๐Ÿš€

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

http_client_benchmarker-5.0.0.tar.gz (134.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

http_client_benchmarker-5.0.0-py3-none-any.whl (26.7 kB view details)

Uploaded Python 3

File details

Details for the file http_client_benchmarker-5.0.0.tar.gz.

File metadata

File hashes

Hashes for http_client_benchmarker-5.0.0.tar.gz
Algorithm Hash digest
SHA256 c5e401db57971d6fea45188d1b664edc65bc21355ac499ba5f4e0a0ada0782e3
MD5 cb6b093eb84ab7bd09c32bdeba60cc4b
BLAKE2b-256 c58262d8d1d817c12df775c3f3919acd9dab1e6ae5bab049198952a0bd4f7232

See more details on using hashes here.

File details

Details for the file http_client_benchmarker-5.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for http_client_benchmarker-5.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 b4ff61aafbf45da42092fbae269ee4c0d3cbca08be21938d6a8c50f61f9fbd4f
MD5 3f4399309878c29174f80da842b9b5a4
BLAKE2b-256 98e5d655bbfa0f382d1602a6a841d073d322606ce37874d76c517a1b817c5a2b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page