Skip to content

Repository files navigation

CloudflareBench

A high-throughput, massively-parallel file downloader for .NET that doubles as a Cloudflare CDN analyzer — it measures real download performance while surfacing per-request cache status, edge PoP, and time-to-first-byte pulled straight from Cloudflare's response headers.

build

Point it at a list of URLs and it will saturate your connection across hundreds of concurrent transfers, then break down — file by file and in aggregate — how fast each one went, whether it was served from cache, and which Cloudflare edge location answered.

Platform: Windows (WinForms UI), .NET 8. The download engine itself has no UI dependencies and is a plain reusable class.


Why it exists

Generic download managers tell you how fast. When the origin sits behind Cloudflare, the more interesting questions are why a transfer was fast or slow: was it a cache HIT or a MISS back to origin? Which PoP served it? How much of the latency was time-to-first-byte versus transfer? CloudflareBench answers those while pushing enough parallelism to actually find the ceiling.

Features

  • Unbounded parallelism, under control. Downloads run concurrently through a SemaphoreSlim gate (default: unlimited, configurable). A single tuned SocketsHttpHandler is shared across all transfers with HTTP/2 multiplexing, 100 connections per server, and a warm connection pool.
  • Live per-file telemetry: status, progress, size, instantaneous speed (sampled every 100 ms), TTFB, HTTP status, and errors — updated on a throttled 50 ms cadence so the UI stays responsive under load.
  • Aggregate dashboard: current / average / peak throughput, total bytes, ETA, and active-transfer count, recomputed every 200 ms.
  • Cloudflare intelligence parsed from each response:
    • CF-Cache-Status bucketed into HIT / MISS / EXPIRED / DYNAMIC counters
    • Edge PoP extracted from CF-RAY, with a live per-PoP distribution
    • cf-polished, Age, Server, ETag, CF-Request-ID surfaced per file
  • Robust file handling: streams directly to disk with a 1 MB async buffer (FileOptions.Asynchronous | SequentialScan), sanitizes filenames from URLs, and auto-deduplicates collisions (file.binfile_1.bin).
  • Cancellation everywhere: a global stop plus per-item cancellation, all wired through linked CancellationTokenSources.

How it works

MainForm (WinForms)
   │  events: progress / completed / failed / stats
   ▼
DownloadEngine  ──shared──▶  SocketsHttpHandler (HTTP/2, pooled, 100 conn/server)
   │
   ├── SemaphoreSlim(maxParallel) gate
   ├── per-item Task: stream → 1 MB buffer → FileStream
   ├── per-item stats: TTFB, speed, ETA        (throttled UI events)
   └── background loop: aggregate speed/peak/ETA (every 200 ms)

The engine (Engine/DownloadEngine.cs) is deliberately UI-agnostic: it exposes events and a small imperative API (AddUrls, StartAllDownloadsAsync, StopAllDownloads, CancelDownload) and knows nothing about WinForms. The form is a thin presentation layer over it.

Process-level tuning in Program.cs lifts the framework's default throttles for this workload: DefaultConnectionLimit = 1000, Nagle and Expect: 100-continue disabled, and a pre-warmed thread pool (SetMinThreads(100, 100)).

Build & run

Requires the .NET 8 SDK on Windows.

git clone https://github.com/astralmaster/CloudflareBench.git
cd CloudflareBench
dotnet build -c Release
dotnet run -c Release

Usage

  1. Paste one URL per line into the URLs box.
  2. Pick an output directory, and optionally cap Parallel Downloads and Buffer Size.
  3. Start. Watch the per-file grid and the Statistics / Cloudflare Stats panels fill in live.
  4. Stop cancels everything cleanly; Clear resets the queue.

Only download from servers you own or are authorized to test — at high parallelism this generates substantial load.

Design notes

  • One handler, many requests. Creating an HttpClient per download is the classic socket-exhaustion bug; here a single SocketsHttpHandler with a bounded, long-lived connection pool backs every transfer.
  • Timeouts are per-request, not global. The client's own timeout is disabled and each transfer manages its own linked token, so one slow file can be cancelled without touching the rest.
  • UI updates are throttled at the source. Progress and stats events are rate-limited inside the engine (50 ms / 200 ms), so a thousand active transfers don't flood the UI thread.

License

MIT — see LICENSE.

About

High-throughput parallel file downloader with live Cloudflare CDN cache and PoP analysis (.NET 8).

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages