netscrew.dev/commands/bench
Command

n bench

How fast is a share or host — and WHY: path, protocol, then throughput

Short forms:b · be · bm · speed · speedtest

Usage — n bench

═══════════════════════════════════════════════════════════════════════════════
  Netscrew ("n") — bench (b, be, bm) — How fast is a share or host — and WHY: path, protocol, then throughput
═══════════════════════════════════════════════════════════════════════════════

USAGE:
  n b //host/share                     all six phases: path, protocol, small files, throughput, baseline, verdict (~20 s, ≤96 MB, asks first)
  n b <host>                           phases 1–2 only: path + protocol — any SMB server, no mount, writes nothing
  n b .                                this machine's own disk: the baseline every share is compared against
  n b //host/share --full              256 MB × 5 rounds, for a confident answer

OPTIONS:
  --yes                            skip the 'someone's disk' confirmation
  --at <dir>                       write via this mount point instead of the one I find

Target: . = this machine · <host> = remote
Deeper: n b -h = the concept/theory behind this command  ·  n mount .  ·  n resolve <host>  ·  n drops .

The concept behind it — n bench -h

═══════════════════════════════════════════════════════════════════════════════
  n bench — how fast is a share, and why
═══════════════════════════════════════════════════════════════════════════════

# `n bench` — how fast is a share, and *why*

`n bench //host/share` measures what you actually experience when you use a network share, then
explains it: which link you're on, what the two ends agreed to, where the time goes, and what
is — and isn't — the bottleneck. The numbers are the evidence. The verdict is the product.

```
n bench //host/share          all six phases (~20 s, ≤96 MB of test data, asks first)
n bench <host>                phases 1–2 only: path + protocol. Any SMB server, no mount, writes nothing
n bench .                     this machine's own disk and pressure: the baseline every share is compared against
n bench //host/share --full   256 MB × 5 rounds when you need a confident answer
--yes    skip the "someone's disk" confirmation      --at <dir>   write via a specific mount point
```

## Why most share benchmarks lie

- **They measure caches.** Writing a file returns before the bytes reach the server (write-behind).
  Reading a file you just wrote comes from your own RAM. `n bench` fsyncs every write inside the
  timing, reads a file from an *earlier* round, and bypasses the page cache when it reads
  (`fadvise DONTNEED` on Linux, `FILE_FLAG_NO_BUFFERING` on Windows, `F_NOCACHE` on macOS).
- **They average two different physical quantities.** Small files measure per-operation latency —
  round trips plus whatever the server does per file. Big streams measure throughput. Averaging
  4 KB results with 1 MB results produces a number that means nothing. `n bench` reports the two
  regimes separately and reasons about each.
- **They use fixed sizes.** 1 MB on gigabit is 8 ms — all overhead. `n bench` streams for a fixed
  *time* (4 MB chunks, capped) so the number is stable on any link, from 2.4 GHz Wi-Fi to 10 GbE.
- **They report the mean.** The mean hides the 300 ms stall you actually feel. `n bench` reports
  median and worst.
- **They report a number without a reference.** "44 MB/s" is meaningless until you know the link's
  ceiling. `n bench` derives the ceiling from the negotiated link and shows every result as a
  percentage of it.
- **They don't tell you when to distrust them.** `n bench` runs several rounds, discards the first
  (warm-up), prints the round-to-round spread as a confidence gauge, and says plainly when a
  result is noisy.

## The six phases

### 1 · PATH — how am I reaching it?
Written before anything else because it explains most results on its own.

| Line | What it tells you |
|---|---|
| **Target** | Which address was measured and why. A LAN address is preferred over a Tailscale/VPN one, and it says so when your resolver only knew the slower route. |
| **Interface** | The local interface the kernel routes through; wired or wireless; **negotiated** speed, duplex, MTU. A gigabit NIC negotiated at 100 Mb/s is almost always a cable (gigabit needs all 8 wires) or a dead switch port. A 2.5 GbE NIC at 1 Gb/s means the switch or cable is the limit. |
| **Wi-Fi** | Band, channel, bitrate, signal. 2.4 GHz is slow and crowded; the bitrate sets a hard ceiling. |
| **Ceiling** | The best this link could ever deliver in MB/s, and the assumption behind it (wired ≈ 90 % of line rate; Wi-Fi ≈ 45 % of bitrate because it's half-duplex and shared). |
| **RTT** | 20 TCP connects to the SMB port — the round trip SMB pays on every request. Over ~20 ms is WAN/VPN territory and small-file work suffers most. |
| **MTU test** | A don't-fragment ping. If 1500-byte frames don't fit, a tunnel is shrinking the path and every big packet is split and reassembled. |
| **Hops** | From the reply's TTL; also reveals the remote OS (Windows starts at 128, Linux/macOS at 64). |
| **NIC health** | Drops and errors on the interface since boot. Errors mean corrupted frames: cable, port or card. |
| **Tailscale** | Direct peer-to-peer, or relayed through a DERP server on the internet. Relayed is the difference between LAN speed and a few MB/s. |

### 2 · PROTOCOL — what did the two ends agree on?
`n bench` speaks a raw **SMB2 NEGOTIATE** to port 445 — the first packet every client sends — so it
needs no mount, no password and no admin rights, and works against any SMB server (Windows, Samba,
a NAS).

- **Dialect** the server offers (3.1.1 is current; 2.x lacks multichannel, encryption and large reads).
- **Signing** enabled / **required**. Signing puts an HMAC on every packet: tamper-proof, but 20–50 %
  of gigabit throughput, CPU-bound on both ends. Windows 11 24H2 requires it by default — the tool
  says so rather than telling you to turn it off.
- **Encryption** ciphers available; **multichannel**; **compression**; **max read/write sizes**;
  server **uptime**.
- **SMB1** probe. SMB1 is deprecated (2014) and was WannaCry's way in. If a server still answers
  it, that's flagged with the command to disable it.
- **This client:** what *your* mount actually negotiated (dialect, signing, cache mode, I/O sizes,
  encryption) and, from Linux, what the server says about the volume behind the share (SSD, TRIM,
  sector size) — so the verdict doesn't guess "maybe it's a slow disk" when the server has said it's an SSD.

### 3 · OPS — small files
64 × 4 KB: create → write → close → read → delete, one at a time. This is what copying a source
tree or a photo folder feels like. Reported as files/s and per-file median/worst, against what the
round trips alone would explain (~5 × RTT). A big gap means the server is doing work per file:
Defender scanning every file on close (Windows), or `strict sync` / VFS modules / a high log level
(Samba), or a slow metadata disk.

### 4 · THROUGHPUT — big streaming transfer
Rounds of fixed-time writes (random data, made unique per chunk so nothing compresses or dedups it,
fsync inside the timing) and cache-bypassed reads of the previous round's file. First round is
warm-up and excluded. Shown as MB/s, as a percentage of the ceiling with a bar, with the spread.

### 5 · BASELINE — this machine
The same ops and throughput tests on your own disk (the home directory — `/tmp` may be RAM), plus
this machine's **pressure**: cores against load (or CPU %), and how full the disk is. Without this,
"the share is slow" and "my disk is slow" are indistinguishable. `n bench .` runs this alone; run it
on the *server* when the verdict points there.

### 6 · VERDICT
The result's shape against the ceiling decides the story:

- **wire-limited** — reads and writes both ≥ 80 % of the ceiling. Everything is keeping up; only a
  faster link would help (and it says whether your NIC could take one).
- **write-side** — reads fine, writes slow: the limit is on the server at write time. Suspects, in
  order: Defender scan-on-close (Windows) or `strict sync` (Samba), the server's disk (unless it
  reported an SSD), write-through.
- **read-side** — the reverse: the server serving data (a cold HDD, a busy server, small `rsize`).
- **both** — the path or the protocol: Tailscale relay, encryption or signing, the Wi-Fi radio,
  fragmentation, a server that's simply overloaded — or your own disk, if the baseline is no faster.

Each suspect comes with the exact command to check or fix it, labelled as inference ("in order of
likelihood"), followed by what the evidence *cleared*, the noise paragraph, and the cleanup line.

## Using it on a home network

- **"Is it the Wi-Fi?"** Run it once on Wi-Fi, once on a cable. Phase 1's ceiling and Phase 4's
  percentage settle it in a minute.
- **A cable or switch port that's silently gone bad.** Phase 1: "NIC can do 1000 Mb/s but negotiated 100".
- **Before/after a change** — new switch, new cable, moving a server to a faster port, enabling
  jumbo frames, changing a Samba setting. Same command, compare the numbers *and* the spread.
- **The server, not the network.** Reads at 97 % of the wire and writes at 39 % is a server-side
  signature; the verdict tells you to run `n bench .` *there*, which reports its cores, load and
  disk fullness.
- **Security posture as a side effect.** SMB1 still enabled? Signing off on a server that should
  require it? Insecure guest logons enabled on a Windows client? Phase 2 says so.
- **Tailscale users:** if a share feels slow from your laptop, Phase 1 will tell you whether you're
  going through a relay — and that the LAN address would be ~100× better when you're at home.

A real example: a share served at 12 MB/s and 26 ms per file over a clean gigabit LAN. Phases 1–2
cleared the wire, MTU, signing and VPN; Phase 3 showed per-file time far beyond the round trips;
the verdict pointed at the server. `n bench .` on the server: *2 cores · load 13.9 · oversubscribed
×7 · disk 97 % full.* The SMB daemon wasn't busy — it was starved, waiting in the run queue behind a
browser and a torrent client. No network tool would have found that; a benchmark that only prints
MB/s wouldn't have either.

## Honest limits

- Results are noisy by nature: other transfers, backup jobs, thermal throttling, an antivirus scan
  mid-run. The spread is printed for exactly this reason; over 25 %, rerun. `--full` runs longer.
- Without an agent on the far end, `n bench` measures *the share as you experience it*. It can
  infer where the time goes, but it cannot see the server's CPU or disk directly — hence "run
  `n bench .` on the server".
- Linux/macOS need the share mounted to write to it (`n mount //host/share`); Windows can use the
  UNC path directly. Live session details on Windows need an elevated window.
- It writes to someone's disk and uses someone's network. It asks first, uses a temp folder
  `.netscrew-bench-<random>/`, keeps to ~96 MB by default, and always removes what it wrote.

## Roadmap

- `--json` for tracking a share over time.
- `n bench serve` on the far end for a raw TCP throughput test independent of SMB (like iperf3),
  which would separate "the network" from "the file server" directly.
- Per-host memory of the confirmation, if the prompt grates.