Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .specify/feature.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"feature_directory": "specs/002-win-aot-release"
"feature_directory": "specs/003-profile-cli-switch"
}
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,13 @@ For most users, running a simple speed test is as easy as:
NetPace
```

For common scenarios and advanced usage (such as scripting, restricting payload size, or customising output), see the [User Guide](https://github.com/FrankRay78/NetPace/blob/main/USER_GUIDE.md).
On a metered or IoT connection? Use the Tiny profile (≤ 1 MiB total per run):

```bash
NetPace --profile tiny
```

For common scenarios and advanced usage (such as scripting, restricting payload size, choosing a traffic profile, or customising output), see the [User Guide](https://github.com/FrankRay78/NetPace/blob/main/USER_GUIDE.md).

`NetPace --help` will display detailed usage instructions.

Expand Down Expand Up @@ -109,6 +115,7 @@ OPTIONS:
'NetPace servers -l' will return your nearest servers.
-t, --timestamp Include a timestamp in the output.
--datetimeformat yyyy-MM-dd HH:mm:ss The datetime format string, as defined by Microsoft.Net.
--profile Medium Profile bundle of payload settings (Tiny | Small | Medium | Large | Mega).
--downloadsize Stop the download test after this many megabytes (IEC MiB).
--uploadsize Stop the upload test after this many megabytes (IEC MiB).
-u, --unit BitsPerSecond The speed unit. <BitsPerSecond, BytesPerSecond>
Expand Down
38 changes: 38 additions & 0 deletions USER_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,44 @@ NetPace --downloadsize 50 --uploadsize 20

---

## Choosing a profile

The `--profile` flag bundles per-request payload sizes, parallelism, and a total-byte
cap into one switch. Pick the profile that matches your link, and NetPace adapts the
traffic shape to suit it. `Medium` is the default.

| Profile | Use it when… | Total per run (down + up, approx) |
|---|---|---|
| `Tiny` | IoT / 10 MB-month plans — minimal traffic, single small request | ≤ 1 MiB (~245 KB + ~50 KB) |
| `Small` | Cellular / metered — small budget, modest parallelism | ≤ 12 MiB (~10 MiB + ~2 MiB) |
| `Medium` | Typical home broadband — the default | ≤ 125 MiB (~100 MiB + ~25 MiB) |
| `Large` | Fibre / business — saturates gigabit links | ≤ 1.25 GiB (~1 GiB + ~256 MiB) |
| `Mega` | Inter-DC / 10 Gbps — saturates fibre, see warning below | ≤ 12 GiB (~10 GiB + ~2 GiB) |

Decision guide:

- Cellular or metered IoT? → `--profile small` (or `tiny` for the most miserly plans).
- Most users / home broadband? → no flag needed (Medium default).
- Gigabit fibre or business link? → `--profile large`.
- 10 Gbps inter-DC saturation? → `--profile mega`.

You can still pin a hard cap on top of a profile — the profile sets per-request shape,
`--downloadsize` / `--uploadsize` override only the total cap:

```bash
NetPace --profile large --downloadsize 200
```

> [!WARNING]\
> **`--profile mega` uses undocumented OoklaServer payloads** (`5000`, `6000`, `7000`)
> which are not part of the historic Speedtest.net Flash-client array. The selected
> server may not host them; future OoklaServer releases may break this profile. If
> Mega returns short reads or errors, fall back to `--profile large`. See
> [docs/architecture/download-upload-size-controls.md](https://github.com/FrankRay78/NetPace/blob/main/docs/architecture/download-upload-size-controls.md)
> for the per-request payload tables and the fallback strategy.

---

For more options and details, run:
```bash
NetPace --help
Expand Down
75 changes: 57 additions & 18 deletions docs/architecture/download-upload-size-controls.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,32 @@ Source: [`OoklaSpeedtestSettings.cs`](../../src/NetPace.Core/Clients/Ookla/Ookla

Source: [`Settings/DownloadTestSettings.cs`](../../src/NetPace.Core/Clients/Ookla/Settings/DownloadTestSettings.cs).

| Property | Default | Meaning |
Defaults below are the values supplied by `new OoklaSpeedtestSettings()` (which chains to `Profile.Medium`). A bare `new DownloadTestSettings()` uses the type's field initializers (`DownloadSizeIterations = 4`, `DownloadParallelTasks = 8`, `DownloadSizeMb = int.MaxValue`); see §5 for per-profile values.

| Property | Default (Medium profile) | Meaning |
| ------------------------ | -------------------------------- | -------------------------------------------------------------------------------------- |
| `DownloadSizes` | `[1500, 2000, 3000, 3500, 4000]` | Pixel sizes used to build URLs of the form `random{N}x{N}.jpg`. Bigger N → bigger file. The default is the larger half of the historic ten-element Ookla Flash-client array (see §2.1). |
| `DownloadSizeIterations` | `4` | How many times each size is requested (URL gets a `?r={i}` cache-buster). |
| `DownloadParallelTasks` | `8` | Concurrent HTTP GETs. |
| `DownloadSizeIterations` | `2` | How many times each size is requested (URL gets a `?r={i}` cache-buster). |
| `DownloadParallelTasks` | `4` | Concurrent HTTP GETs. |
| `DownloadSizeMb` | `100` | Total-byte budget cap in IEC MiB. The download loop terminates once cumulative bytes received reach this threshold. Default sentinel for a bare record is `int.MaxValue` (no cap). |

Total candidate requests = `DownloadSizes.Length × DownloadSizeIterations` (default = 5 × 4 = **20**).
Total candidate requests = `DownloadSizes.Length × DownloadSizeIterations` (Medium default = 5 × 2 = **10**).

### 1.2 `UploadTestSettings`

Source: [`Settings/UploadTestSettings.cs`](../../src/NetPace.Core/Clients/Ookla/Settings/UploadTestSettings.cs).

| Property | Default | Meaning |
| ----------------------- | ------- | ------------------------------------------------------------------------------------ |
| `UploadSizeIncrementKb` | `200` | Step size between successive increments, in KB (binary, ×1024). |
| `UploadIncrements` | `6` | Number of increments (200 KB, 400 KB, 600 KB, 800 KB, 1 MB, 1.2 MB). |
| `UploadSizeIterations` | `10` | How many times each increment is repeated. |
| `UploadParallelTasks` | `8` | Concurrent HTTP POSTs. |
Defaults below are the values supplied by `new OoklaSpeedtestSettings()` (Medium profile). A bare `new UploadTestSettings()` uses the type's field initializers (`UploadSizeIterations = 10`, `UploadParallelTasks = 8`, `UploadSizeMb = int.MaxValue`); see §5 for per-profile values.

| Property | Default (Medium profile) | Meaning |
| ----------------------- | ------------------------ | ------------------------------------------------------------------------------------ |
| `UploadSizeIncrementKb` | `200` | Step size between successive increments, in KB (binary, ×1024). |
| `UploadIncrements` | `6` | Number of increments (200 KB, 400 KB, 600 KB, 800 KB, 1 MB, 1.2 MB). |
| `UploadSizeIterations` | `5` | How many times each increment is repeated. |
| `UploadParallelTasks` | `4` | Concurrent HTTP POSTs. |
| `UploadSizeMb` | `25` | Total-byte budget cap in IEC MiB. Default sentinel for a bare record is `int.MaxValue` (no cap). |

Total candidate requests = `UploadIncrements × UploadSizeIterations` (default = 6 × 10 = **60**).
Total candidate requests = `UploadIncrements × UploadSizeIterations` (Medium default = 6 × 5 = **30**).

## 2. How the settings shape network behaviour

Expand Down Expand Up @@ -175,16 +181,19 @@ Unlike download, this total is fully deterministic — NetPace generates the pay

## 3. CLI surface

[`Program.cs`](../../src/NetPace.Console/Program.cs) exposes only the two budget caps, wired into [`SpeedTestCommandSettings`](../../src/NetPace.Console/Commands/SpeedTestCommandSettings.cs):
[`Program.cs`](../../src/NetPace.Console/Program.cs) exposes one profile selector and two budget-cap overrides, wired into [`SpeedTestCommandSettings`](../../src/NetPace.Console/Commands/SpeedTestCommandSettings.cs):

| Switch | Property | Default | Effect |
| ---------------- | ---------------- | -------------- | ------------------------------------------------------------------------------------- |
| `--downloadsize` | `DownloadSizeMb` | `int.MaxValue` | Stops the download test after N MiB total. Does **not** change per-request file size. |
| `--uploadsize` | `UploadSizeMb` | `int.MaxValue` | Stops the upload test after N MiB total. Does **not** change per-request payload. |
| Switch | Property | Default | Effect |
| ---------------- | ---------------- | ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
| `--profile` | `Profile` | `Medium` | Sets per-request shape (`DownloadSizes`, iterations, parallel tasks) and total-byte cap defaults via `new OoklaSpeedtestSettings(p)`. |
| `--downloadsize` | `DownloadSizeMb` | (profile-supplied) | Overrides the download cap via a `with`-expression. Does **not** change per-request file size — the profile remains authoritative for shape. |
| `--uploadsize` | `UploadSizeMb` | (profile-supplied) | Overrides the upload cap via a `with`-expression. Does **not** change per-request payload — the profile remains authoritative for shape. |

> **Important distinction:** these are **total-byte budget caps**, not per-request size controls. The per-request sizes (`DownloadSizes`, `UploadSizeIncrementKb`, etc.) are hard-wired to the defaults above and are reachable only via the `NetPace.Core` library API, not the CLI.
> **Important distinction:** `--downloadsize` / `--uploadsize` are **total-byte budget caps**, not per-request size controls. The per-request sizes (`DownloadSizes`, `UploadSizeIncrementKb`, etc.) are set by the chosen profile and are otherwise reachable only via the `NetPace.Core` library API, not the CLI.
>
> Both defaults are `int.MaxValue` MiB, which is far larger than any iteration would ever transfer — so the cap is **inactive by default**. With defaults, NetPace will transfer the full totals computed in §2.1 and §2.2 (≈ 328 MiB down, ≈ 41 MiB up).
> When `--downloadsize` / `--uploadsize` are omitted, the profile-supplied caps apply (e.g. Medium = 100 MiB down + 25 MiB up). To see all five profile shapes at once, see §5.

The library-level cap-removal default — a fresh `new DownloadTestSettings()` literal (no profile) — is `int.MaxValue` MiB, which is far larger than any iteration would ever transfer, so the cap is **inactive** in that bare-record case.

## 4. Local verification

Expand All @@ -207,3 +216,33 @@ curl -sS -o /dev/null -w '%{size_download} bytes in %{time_total}s\n' \
head -c 1048576 /dev/urandom | curl -sS -o /dev/null -w '%{http_code}\n' \
--data-binary @- http://localhost:18080/speedtest/upload.php
```

## 5. Profile-driven defaults

[`Profile`](../../src/NetPace.Core/Profile.cs) is the public, provider-agnostic vocabulary surfaced via `--profile`. [`OoklaSpeedtestSettings(Profile)`](../../src/NetPace.Core/Clients/Ookla/OoklaSpeedtestSettings.cs) maps each profile to a complete `DownloadTestSettings` / `UploadTestSettings` pair via an inline switch — the single source of truth for "what does Tiny mean, in Ookla terms?".

### 5.1 Download (per profile)

| Profile | `DownloadSizes` | Iterations | Parallel | `DownloadSizeMb` cap |
| -------- | ----------------------------------- | ---------- | -------- | -------------------- |
| `Tiny` | `[350]` | 1 | 1 | 1 |
| `Small` | `[1000, 1500]` | 2 | 2 | 10 |
| `Medium` | `[1500, 2000, 3000, 3500, 4000]` | 2 | 4 | 100 |
| `Large` | `[2000, 2500, 3000, 3500, 4000]` | 12 | 16 | 1024 |
| `Mega` | `[3000, 4000, 5000, 6000, 7000]` | 40 | 32 | 10240 |

### 5.2 Upload (per profile)

| Profile | `UploadSizeIncrementKb` | `UploadIncrements` | Iterations | Parallel | `UploadSizeMb` cap |
| -------- | ----------------------- | ------------------ | ---------- | -------- | ------------------ |
| `Tiny` | 50 | 1 | 1 | 1 | 1 |
| `Small` | 100 | 4 | 2 | 2 | 2 |
| `Medium` | 200 | 6 | 5 | 4 | 25 |
| `Large` | 500 | 8 | 12 | 16 | 256 |
| `Mega` | 1024 | 16 | 16 | 32 | 2048 |

### 5.3 Mega is the only profile relying on the bonus payloads

The `5000`, `6000`, `7000` pixel-size payloads identified in §2.1 are **only used by `Mega`**. The other four profiles stay within the historic Flash-client `random{N}x{N}.jpg` array, so they are guaranteed to work against any OoklaServer that ships those URLs (every server we've probed — see §2.1 Cross-server validation).

If a future OoklaServer release drops the bonus payloads, Mega will see 404s on those URLs and fall back to whatever the surviving subset returns. The current Mega arm is tuned for the bonus payloads being present; the *documented fallback strategy* — revert Mega to the historic-10 array with higher iteration counts to keep total transfer in the ~10 GiB band — is tracked but **not implemented in the 003-profile-cli-switch change**. Users who hit Mega-specific 404s should switch to `--profile large` until the fallback lands.
Loading
Loading