Test Sequence
The speed test follows a structured sequence of phases (from main.go:43-70):- Initialization - Fetch network metadata
- Unloaded Latency - Measure baseline latency (20 samples)
- Download Phase - Throughput and loaded latency measurement
- Upload Phase - Throughput and loaded latency measurement
- Packet Loss Test - Reliability measurement (1,000 requests)
- Results Compilation - Calculate final metrics and display results
Download Phase
Test Sizes and Repetitions
The download phase uses four different payload sizes, each tested multiple times (main.go:59-61):| Size | Repetitions | Purpose |
|---|---|---|
| 101 KB | 10 | Quick warmup and low-bandwidth measurement |
| 1 MB | 8 | Medium file transfer simulation |
| 10 MB | 6 | Large file transfer simulation |
| 25 MB | 4 | Sustained high-throughput measurement |
Timing Measurement
Each download test measures the time between:- Start: Time to first byte (TTFB) received
- End: All bytes received
Loaded Latency Monitoring
During the download phase, a background goroutine continuously monitors latency:- Probe frequency: Every 200 milliseconds
- Probe type: Lightweight 0-byte request
- Duration: Entire download phase
Upload Phase
Test Sizes and Repetitions
The upload phase uses the same sizes but different repetition counts (main.go:65-66):| Size | Repetitions | Purpose |
|---|---|---|
| 101 KB | 8 | Quick warmup and low-bandwidth measurement |
| 1 MB | 6 | Medium file transfer simulation |
| 10 MB | 4 | Large file transfer simulation |
| 25 MB | 4 | Sustained high-throughput measurement |
Payload Generation
Upload tests generate a payload of the specified size filled with zeros:Timing Measurement
Upload speed relies on server-side timing reported in the response:Unloaded Latency Test
Sample Collection
Baseline latency is measured before any throughput tests (main.go:50-52):- Number of samples: 20
- Request size: 0 bytes
- Endpoint:
/__down?bytes=0 - Method: Sequential (not concurrent)
Latency Calculation
Each sample measures network round-trip time minus server processing:pd.Started: Request initiation timestamppd.TTFB: Time to first byte receivedpd.ServerTiming: Server-reported processing time
Packet Loss Test
Test Parameters
The packet loss test runs after throughput measurements (main.go:70):- Total requests: 1,000
- Concurrency limit: 50 simultaneous requests
- Request type: GET
/__down?bytes=0 - Success criteria: HTTP 200 status code
Execution Strategy
Requests are sent concurrently using a semaphore to limit parallelism:Loss Calculation
Packet loss is calculated as:Statistical Methods
The tool uses several statistical functions from thestats package to process raw measurements.
Median
Used for latency and intermediate progress reporting:Quartile (Percentile)
Used for final throughput calculations (90th percentile):Jitter
Calculates average variability between consecutive latency measurements:Why 90th Percentile for Throughput?
The tool uses the 90th percentile (stats.Quartile(speeds, 0.90)) for final download and upload speeds:
Advantages:
- Outlier filtering: Removes the slowest 10% of samples that may be affected by transient issues
- Sustained performance: Better represents achievable speeds under normal conditions
- Optimistic but realistic: Higher than median but not peak performance
- Industry alignment: Common metric in SLAs and network benchmarking
- Average: Too sensitive to outliers
- Median (50th percentile): Too conservative, doesn’t reflect capable speeds
- Maximum: Unrealistic, represents best-case scenario only
Test Endpoint Details
All measurements use Cloudflare’s speed test API endpoints:- Download:
GET /__down?bytes={size} - Upload:
POST /__upwith payload - Latency probe:
GET /__down?bytes=0