A Python HTTP Client Performance Benchmark Framework
Project description
โก HTTP Client & Server Performance Benchmark Framework
๐ 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:
- Configure: Define client, server, method, and concurrency parameters.
- Execute: Launch high-frequency requests while monitoring system resources in the background.
- Analyze: Aggregate performance metrics including throughput and latency percentiles.
- Persist: Store detailed results in SQLite for historical analysis.
- Report: Visualize comparative data directly in your terminal.
๐ Installation
๐ Prerequisites
- Python 3.12+
- Docker & Docker Compose (for running isolated test servers)
๐ง Setup
-
Clone the repository:
git clone https://github.com/your-repo/http-client-benchmarker.git cd http-client-benchmarker
-
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
- Create a new adapter in
http_benchmark/clients/inheriting fromBaseAdapter. - Register the adapter in
http_benchmark/benchmark.pywithinBenchmarkRunner. - 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
ThreadPoolExecutorwith optimized pool sizing. - Asynchronous Clients: Powered by
asynciowith 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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
File details
Details for the file http_client_benchmarker-5.1.0.tar.gz.
File metadata
- Download URL: http_client_benchmarker-5.1.0.tar.gz
- Upload date:
- Size: 133.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
345ed8ce81078128fdf064878c4329e3f7b382334591bc3e8e941fdf3e93f09c
|
|
| MD5 |
227e0ab12047d60893b508755e11394a
|
|
| BLAKE2b-256 |
4327d6e992f095b5f259386d75434ebc770a896ffa2d6117f470b40ad538da8e
|