Benchmark Azure Blob Storage upload performance with varying chunk sizes and concurrency levels.
Project description
azure-upload-benchmark
Benchmark Azure Blob Storage upload performance with varying chunk sizes and concurrency levels.
Runs a configurable grid of (chunk_size, concurrency) combinations, records timing data, and produces CSV/JSON results plus optional heatmap and line plots to help you find optimal upload settings.
Installation
Requires Python 3.10+
uvx azure-upload-benchmark --help
Or install globally:
uv tool install azure-upload-benchmark
With pip / pipx:
pipx install azure-upload-benchmark
# or
pip install azure-upload-benchmark
To enable plot generation (heatmaps, line plots, 3-D surface):
uv tool install "azure-upload-benchmark[plots]"
# or
pipx install "azure-upload-benchmark[plots]"
From source
git clone https://github.com/pshrest2/azure-upload-benchmark.git
cd azure-upload-benchmark
uv sync --extra dev
Quick Start
Using a pre-signed SAS URL
azure-upload-benchmark --sas-url "https://myaccount.blob.core.windows.net/..." --file path/to/data.bin
Using an upload API
If you have an API that generates SAS URLs on demand:
azure-upload-benchmark \
--api-url "https://example.com/api/uploads/url" \
--token "your-bearer-token" \
--file path/to/data.bin
The --api-url endpoint must accept a POST with {"filename": "..."} and return {"url": "<sas_url>"}.
Generate a synthetic test file
azure-upload-benchmark --sas-url "https://..." --generate-file 500
Custom benchmark grid
azure-upload-benchmark \
--sas-url "https://..." \
--file test.bin \
--chunk-sizes 4 8 16 32 \
--concurrencies 1 2 4 8 16 \
--repeat 3
Cleanup after uploads
If your API supports deleting uploaded files, pass --delete-url to remove each blob after benchmarking:
azure-upload-benchmark \
--api-url "https://example.com/api/uploads/url" \
--delete-url "https://example.com/api/uploads" \
--token "your-bearer-token" \
--file test.bin
Regenerate report from existing data
azure-upload-benchmark --report --output-dir benchmark_results
CLI Options
| Option | Description |
|---|---|
--sas-url |
Pre-signed Azure Blob SAS URL with write permission |
--api-url |
POST endpoint returning {"url": "<sas_url>"} |
--delete-url |
DELETE endpoint for cleanup after each upload |
--token |
JWT Bearer token for the API endpoints (only Bearer auth is currently supported) |
--file |
Path to the file to upload |
--generate-file SIZE_MB |
Generate a synthetic test file of the given size |
--chunk-sizes MB [MB ...] |
Chunk sizes in MB (default: 4 8 10 16 32 64) |
--concurrencies N [N ...] |
Concurrency levels (default: 2 4 8 12) |
--repeat N |
Repetitions per config for averaging (default: 1) |
--output-dir DIR |
Directory for results and plots (default: benchmark_results) |
--report |
Regenerate report/plots from existing CSV |
Output
Results are saved to the output directory:
benchmark_results.csv— tabular resultsbenchmark_results.json— JSON resultsthroughput_heatmap.png— throughput heatmap (requiresplotsextra)upload_time_heatmap.png— upload time heatmapthroughput_line_plots.png— line plots by chunk size and concurrencythroughput_surface_3d.png— 3-D surface plot
Programmatic Usage
from azure_upload_benchmark.upload import upload_blob
from azure_upload_benchmark.results import load_csv, save_csv
from azure_upload_benchmark.plotting import generate_plots
# Single upload
result = upload_blob(
sas_url="https://...",
file_path="data.bin",
chunk_size=8 * 1024 * 1024,
concurrency=4,
)
print(result)
# {'file_size_mb': 100.0, 'chunk_size_mb': 8.0, 'concurrency': 4, 'elapsed_s': 12.5, 'throughput_mbps': 8.0}
# Load existing results and regenerate plots
results = load_csv("benchmark_results/benchmark_results.csv")
generate_plots(results, "benchmark_results")
Package Structure
src/azure_upload_benchmark/
├── __init__.py # Package version
├── api.py # HTTP helpers for SAS URL generation and cleanup
├── benchmark.py # Benchmark orchestration (grid runner)
├── cli.py # Command-line interface
├── constants.py # Shared constants (defaults, field names)
├── plotting.py # Heatmap, line plot, and 3-D surface generation
├── reporting.py # Summary printing and finalization
├── results.py # CSV / JSON persistence
└── utils.py # Test-file generation utilities
Running Tests
uv sync --extra dev
uv run pytest tests/ -v
Development Setup
After cloning the repo, install dependencies and set up pre-commit hooks:
uv sync --extra dev
uv run pre-commit install
uv run pre-commit install --hook-type commit-msg
Conventional Commits
This project enforces Conventional Commits via a pre-commit hook. All commit messages must follow the format:
<type>: <description>
Allowed types: feat, fix, docs, style, refactor, perf, test, build, ci, chore, revert
Examples:
feat: add retry logic for failed uploads
fix: handle empty CSV when loading results
docs: update CLI options table
ci: add Python 3.13 to test matrix
Breaking changes use ! after the type:
feat!: redesign CLI argument structure
Releases and changelogs are generated automatically from these commit messages.
License
MIT
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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file azure_upload_benchmark-0.2.2.tar.gz.
File metadata
- Download URL: azure_upload_benchmark-0.2.2.tar.gz
- Upload date:
- Size: 122.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6f8d86b41ca8f3e109d816e2026e49db7412a320b378e9f8e00d96b87726a32
|
|
| MD5 |
a690ad63ff513179291faf1ed656f432
|
|
| BLAKE2b-256 |
72ac245ab037cc8e5e5d8052e80d171e4a3f730b8f430161f9e5f4ee30d27741
|
Provenance
The following attestation bundles were made for azure_upload_benchmark-0.2.2.tar.gz:
Publisher:
publish.yml on pshrest2/azure-upload-benchmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
azure_upload_benchmark-0.2.2.tar.gz -
Subject digest:
b6f8d86b41ca8f3e109d816e2026e49db7412a320b378e9f8e00d96b87726a32 - Sigstore transparency entry: 1163405971
- Sigstore integration time:
-
Permalink:
pshrest2/azure-upload-benchmark@33139f1cdade47c3577dc934e1b5fb9a1b792c2e -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/pshrest2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33139f1cdade47c3577dc934e1b5fb9a1b792c2e -
Trigger Event:
release
-
Statement type:
File details
Details for the file azure_upload_benchmark-0.2.2-py3-none-any.whl.
File metadata
- Download URL: azure_upload_benchmark-0.2.2-py3-none-any.whl
- Upload date:
- Size: 15.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9109ae935cd0a6d44c5444d23b6b19ad27907491069447d9962101bf2eab7339
|
|
| MD5 |
77f5edb7b87c921827ae3d263af3aed4
|
|
| BLAKE2b-256 |
20e2ebac538ba86a3aa8ae9619dd59ca89e9baad176337525d390b7a7c270cf6
|
Provenance
The following attestation bundles were made for azure_upload_benchmark-0.2.2-py3-none-any.whl:
Publisher:
publish.yml on pshrest2/azure-upload-benchmark
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
azure_upload_benchmark-0.2.2-py3-none-any.whl -
Subject digest:
9109ae935cd0a6d44c5444d23b6b19ad27907491069447d9962101bf2eab7339 - Sigstore transparency entry: 1163406048
- Sigstore integration time:
-
Permalink:
pshrest2/azure-upload-benchmark@33139f1cdade47c3577dc934e1b5fb9a1b792c2e -
Branch / Tag:
refs/tags/v0.2.2 - Owner: https://github.com/pshrest2
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@33139f1cdade47c3577dc934e1b5fb9a1b792c2e -
Trigger Event:
release
-
Statement type: