Skip to content

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

41 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Fil.one S3 Speed Tests

Reusable VM benchmark harness for comparing S3-compatible providers from a Linux test node.

The scripts write JSONL and logs to /dataoutput, use generated payloads in /testfiles, and use /downloads as disposable download scratch space.

VM Setup

Run this on a fresh apt-based Linux VM:

git clone https://github.com/fil-one/s3-speedtests
cd s3-speedtests
sudo ./scripts/setup_vm.sh

The setup installs traceroute, ping, jq, curl, Python, python3-docx, python3-reportlab, Ookla speedtest, and AWS CLI. It also generates:

  • 100 x 1 MiB files
  • 5 x 100 MiB files
  • 1 x 1 GiB file
  • 1 x 25 GiB file
  • 1 x 50 GiB file

To install dependencies without generating the full payload set:

sudo ./scripts/setup_vm.sh --skip-files

To create or repair only the /testfiles payload set after dependencies are already installed:

sudo ./scripts/setup_vm.sh --files-only

To regenerate files even when matching filenames already exist:

sudo ./scripts/setup_vm.sh --files-only --force-files

Test Files on a Developer Machine

To run the scripts from a laptop (macOS or Linux) instead of the VM, generate the payload set without root into any directory and point the scripts at it with --testfiles-dir:

./scripts/generate_test_files.sh ~/s3-testfiles quick     # 1 MiB + 100 MiB
./scripts/generate_test_files.sh ~/s3-testfiles standard  # everything up to 1 GiB
./scripts/generate_test_files.sh ~/s3-testfiles large     # 1 GiB + 25 GiB + 50 GiB
FORCE_FILES=1 ./scripts/generate_test_files.sh ~/s3-testfiles quick  # regenerate even if sizes match

Provider Config

Setup seeds /testfiles/s3_targets.ini from config/s3_targets.example.ini if it does not already exist.

Edit /testfiles/s3_targets.ini, enable the providers you want, and add bucket names. For static-key providers, add access keys there and then write AWS CLI profiles:

./scripts/s3_write_profiles.py

For AWS SSO or temporary AWS credentials, configure the profile directly with AWS CLI and set profile = aws and auth_mode = profile.

S3 commands default to AWS_MAX_ATTEMPTS=11, which means one initial request plus ten retries. Override globally with AWS_MAX_ATTEMPTS=... or per provider with aws_max_attempts = ... in /testfiles/s3_targets.ini.

Common Runs

Run Everything

Warning: run_all executes the full benchmark workflow after setup. It writes AWS CLI profiles from /testfiles/s3_targets.ini, checks access, uploads the standard and large file sets, downloads all uploaded objects, runs network tests and traceroutes, and then builds the default DOCX report. This can move more than 75 GiB per enabled provider in each direction and may incur cloud egress, storage, API, or bandwidth costs.

Run the complete workflow:

./scripts/run_all

Run only selected providers:

./scripts/run_all --providers aws,wasabi

Show AWS CLI transfer progress in the tmux console during upload and download steps:

./scripts/run_all --progress

The same behavior can be enabled with TRANSFER_PROGRESS=1:

TRANSFER_PROGRESS=1 ./scripts/run_all --providers aws,wasabi

Upload and download up to four files concurrently per provider:

./scripts/run_all --parallel

Choose a different concurrency limit with --parallel-workers N. The same settings are available through PARALLEL_TRANSFERS=1 and PARALLEL_WORKERS=N.

By default, run_all uses minimal waits: PAUSE_SECONDS=5, NETWORK_RUNS=1, NETWORK_SLEEP_SECONDS=5, and NETWORK_SERVER_MODE=world. Override them when you want more samples:

NETWORK_RUNS=3 NETWORK_SLEEP_SECONDS=30 PAUSE_SECONDS=10 ./scripts/run_all

The orchestration log is written to /dataoutput/run_all_<timestamp>.log.

The final report step prompts for the source node provider/name and location unless those values are supplied through environment variables:

SOURCE_NODE_PROVIDER="AWS EC2" \
SOURCE_NODE_LOCATION="eu-west-3 | Paris, France" \
SOURCE_NODE_NETWORK="1 Gbit connection" \
./scripts/run_all --providers aws,wasabi

Individual Commands

Check bucket access:

./scripts/s3_access_check.py

Check one provider by target section, provider name, or AWS profile:

./scripts/s3_access_check.py --providers f1
./scripts/s3_access_check.py --providers aws-us-west-2

Print each AWS CLI command plus stdout/stderr for debugging:

./scripts/s3_access_check.py --providers f1 --verbose

Pass AWS CLI --debug for deep troubleshooting. This is very noisy and can include request metadata, so redirect it to a log when needed:

./scripts/s3_access_check.py --providers f1 --debug-aws 2>&1 | tee /dataoutput/f1_access_debug.log

Network baseline:

RUNS=1 ./scripts/network_speedtest_ookla.sh

By default, the network baseline uses the configured world server list so results cover the same explicit cities on every VM. Use NETWORK_SERVER_MODE=auto when only Ookla's nearby/best server is wanted.

Network server modes:

NETWORK_SERVER_MODE=auto RUNS=1 ./scripts/network_speedtest_ookla.sh
NETWORK_SERVER_MODE=world RUNS=1 ./scripts/network_speedtest_ookla.sh
NETWORK_SERVER_MODE=fixed RUNS=1 ./scripts/network_speedtest_ookla.sh
NETWORK_SERVER_MODE=geo RUNS=1 ./scripts/network_speedtest_ookla.sh
NETWORK_SERVER_MODE=all RUNS=1 ./scripts/network_speedtest_ookla.sh

auto uses Ookla's selected server and does not call the Speedtest server-list API. world uses the configured global server list without also running automatic-nearest, preventing the nearest location from duplicating one of the explicit cities. fixed uses the legacy Barcelona, Madrid, and Paris server IDs. geo searches the Speedtest server-list API for the configured city coordinates and may be rate-limited by Ookla. all combines auto, fixed, and geo. Reports also suppress an automatic-nearest row when historical data contains an explicit target for the same resolved city and country.

Provider traceroutes:

./scripts/s3_provider_traceroutes.sh

Traceroutes are generated only for enabled endpoints in /testfiles/s3_targets.ini. An explicit port in endpoint_url is used as the TCP traceroute destination port; otherwise HTTPS endpoints default to 443 (and explicit HTTP URLs default to 80). Use --targets to point at a different target config.

Upload standard and large file sets together:

./scripts/s3_upload_speedtest.sh --file-set full

Show upload progress and per-object elapsed time / throughput in the console:

./scripts/s3_upload_speedtest.sh --file-set full --progress

Upload files concurrently (four workers by default):

./scripts/s3_upload_speedtest.sh --file-set full --parallel
./scripts/s3_upload_speedtest.sh --file-set full --parallel --parallel-workers 8

Run upload file sets separately when you want independent standard and large result files:

./scripts/s3_upload_speedtest.sh --file-set standard
./scripts/s3_upload_speedtest.sh --file-set large

Download all uploaded files:

./scripts/s3_download_speedtest.sh --file-set full

Show download progress and per-object elapsed time / throughput in the console:

./scripts/s3_download_speedtest.sh --file-set full --progress

Download files concurrently (four workers by default):

./scripts/s3_download_speedtest.sh --file-set full --parallel
./scripts/s3_download_speedtest.sh --file-set full --parallel --parallel-workers 8

Parallel mode overlaps files within one provider and repeat. Providers and repeat rounds still run in sequence, and cleanup waits for all downloads in the batch to finish. With --progress, output from simultaneous AWS CLI processes can be interleaved.

With --progress, the AWS CLI progress display streams to the terminal. The scripts still write JSONL metrics and print a final DONE ... elapsed=... throughput_mbps=... line for each object. When progress is enabled through run_all, the orchestration log also captures the console stream because run_all uses tee.

Watch newest logs:

tail -f "$(ls -t /dataoutput/*.log | head -n 1)"

Cleanup Test Objects

Preview deletion of test objects from all enabled providers. This is a dry run by default:

./scripts/s3_cleanup_test_files.py

Actually delete each provider's configured test prefix from all enabled providers:

./scripts/s3_cleanup_test_files.py --execute

Clean only selected providers:

./scripts/s3_cleanup_test_files.py --providers aws,wasabi --execute

Delete a specific prefix instead of each provider's configured prefix:

./scripts/s3_cleanup_test_files.py --providers f1 --prefix test/20260715T185306Z --execute

Delete all objects in selected buckets:

./scripts/s3_cleanup_test_files.py --providers f1 --entire-bucket --execute

Cleanup audit records are written to /dataoutput/s3_cleanup_test_files.jsonl.

Report Builder

Build a summary report from JSONL output in /dataoutput:

./scripts/build_summary_report.py

PDF is the default format. Generated reports are written under /dataoutput/reports.

Choose a report format explicitly:

./scripts/build_summary_report.py --format docx
./scripts/build_summary_report.py --format pdf
./scripts/build_summary_report.py --format both

The report builder loads the latest available benchmark artifacts:

  • /dataoutput/network_speedtest_ookla_summary.jsonl
  • /dataoutput/s3_upload_speedtest_summary.jsonl or the latest s3_upload_speedtest_summary_*.jsonl
  • /dataoutput/s3_download_speedtest_summary.jsonl or the latest s3_download_speedtest_summary_*.jsonl
  • /dataoutput/s3_provider_traceroutes.jsonl or the latest s3_provider_traceroutes_*.jsonl

Upload and download ranking cells include median throughput, average throughput, total elapsed time, and median elapsed time when available. In each total-time chart, a provider with any failed transfer is marked FAILED and ranked after every provider whose transfers all succeeded, so incomplete elapsed time cannot improve its ranking. The traceroute section includes only enabled target endpoints from the target config, plus the full CLI traceroute command output with hop lines.

Provider names and regions in the upload/download result tables are read from /testfiles/s3_targets.ini, so changing a bucket target region there changes the report label on the next report build. Optional display_name and location fields in each target section override the report label, for example display_name = AWS and location = Paris, France. Use --targets to point at a different target config.

When run interactively, the report builder prompts for the source node provider/name and source node location. It auto-detects hostname, vCPU count, and RAM from the VM.

The Test Node section includes the UTC time the benchmark suite started, formatted as 14:07:32 (UTC) on September 20, 2026. scripts/run_all passes this time to the report builder automatically. When rebuilding a report directly, the builder infers an approximate start time from timestamped artifacts in /dataoutput, the first saved network-test record, or a data-file modification time. You can set it explicitly with --tests-started-at-utc 20260920T140732Z.

Prompted run:

./scripts/build_summary_report.py

Expected prompts:

Source node provider/name:
Source node location:

For non-interactive runs:

./scripts/build_summary_report.py \
  --format docx \
  --source-provider "AWS EC2" \
  --source-location "eu-west-3 | Paris, France" \
  --node-network "1 Gbit connection" \
  --no-prompt

You can also use environment variables:

SOURCE_NODE_PROVIDER="AWS EC2" \
SOURCE_NODE_LOCATION="eu-west-3 | Paris, France" \
SOURCE_NODE_NETWORK="1 Gbit connection" \
./scripts/build_summary_report.py --format pdf --no-prompt

Use explicit input and output directories when rebuilding a report from archived results:

./scripts/build_summary_report.py \
  --format both \
  --targets /testfiles/s3_targets.ini \
  --data-dir /dataoutput \
  --output-dir /dataoutput/reports

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages