Measure cached Dosh attach fast path
This commit is contained in:
@@ -201,9 +201,11 @@ make bench-docker-mosh
|
||||
```
|
||||
|
||||
That prints `ssh_true_ms`, `dosh_attach_ms`, and `mosh_start_true_ms` under the same
|
||||
container, key, DNS, and network path. See `docs/PUBLIC_READINESS.md` before using
|
||||
the numbers publicly; Dosh's current strongest claim is fast attach/reconnect, not
|
||||
full Mosh feature parity yet.
|
||||
container, key, DNS, and network path. It also prints `dosh_cached_attach_ms`, which
|
||||
is the real Dosh fast path after the first SSH-authenticated bootstrap has issued an
|
||||
attach ticket. See `docs/PUBLIC_READINESS.md` before using the numbers publicly;
|
||||
Dosh's current strongest claim is fast attach/reconnect, not full Mosh feature
|
||||
parity yet.
|
||||
|
||||
The CI workflow includes an optional remote benchmark job. It runs when
|
||||
`DOSH_BENCH_HOST`, `DOSH_BENCH_USER`, and `DOSH_BENCH_SSH_KEY` repository secrets are
|
||||
|
||||
@@ -27,13 +27,19 @@ Reported metrics:
|
||||
| Metric | Meaning |
|
||||
| --- | --- |
|
||||
| `ssh_true_ms` | Time to run `ssh host true` with the same key/options. |
|
||||
| `dosh_attach_ms` | Time for `dosh-client --attach-only` to render the first frame and detach. |
|
||||
| `dosh_attach_ms` | Time for `dosh-client --attach-only` to render the first frame and detach on the configured path. With `--no-cache`, this is cold SSH bootstrap plus UDP attach. |
|
||||
| `dosh_cached_attach_ms` | Time for a warmed Dosh client to attach using cached UDP credentials/tickets, render the first frame, and detach. This is the fast-path claim and should be approximately network RTT plus local process/render overhead. |
|
||||
| `mosh_start_true_ms` | Time for `mosh host -- true` to bootstrap, run `true`, and exit. |
|
||||
|
||||
These are not identical workloads. They are still useful because they measure the
|
||||
startup path each tool must pay before useful remote work begins. Public numbers
|
||||
must include the command, machine, OS, CPU, network path, and sample count.
|
||||
|
||||
Do not cite cold `dosh_attach_ms` as the core speed claim. Cold Dosh still pays SSH
|
||||
startup/authentication. Cite `dosh_cached_attach_ms` for repeat attach/reconnect
|
||||
speed, and cite cold `dosh_attach_ms` only to show that fallback remains competitive
|
||||
with ordinary SSH.
|
||||
|
||||
## Feature Matrix
|
||||
|
||||
| Feature | Mosh | Dosh now | Public status |
|
||||
|
||||
@@ -31,7 +31,7 @@ for _ in 1 2 3 4 5; do
|
||||
done
|
||||
|
||||
ssh-keyscan -p "$ssh_port" 127.0.0.1 > "$workdir/known_hosts"
|
||||
mkdir -p "$workdir/home" "$workdir/home-controlmaster" "$workdir/home-mosh"
|
||||
mkdir -p "$workdir/home" "$workdir/home-controlmaster" "$workdir/home-cached" "$workdir/home-mosh"
|
||||
|
||||
if ! HOME="$workdir/home" target/release/dosh-bench \
|
||||
--server bench@127.0.0.1 \
|
||||
@@ -64,6 +64,22 @@ if ! HOME="$workdir/home-controlmaster" target/release/dosh-bench \
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if ! HOME="$workdir/home-cached" target/release/dosh-bench \
|
||||
--server bench@127.0.0.1 \
|
||||
--ssh-port "$ssh_port" \
|
||||
--dosh-port "$dosh_port" \
|
||||
--ssh-key "$workdir/id_ed25519" \
|
||||
--ssh-known-hosts "$workdir/known_hosts" \
|
||||
--ssh-auth-command /usr/local/bin/dosh-auth \
|
||||
--iterations 10 \
|
||||
--warm-cache \
|
||||
--skip-ssh-baseline \
|
||||
--assert-dosh-max-ms "${DOSH_BENCH_CACHED_MAX_MS:-25}"; then
|
||||
docker logs "$container_id" || true
|
||||
docker exec "$container_id" sh -lc 'cat /tmp/dosh-server.log 2>/dev/null || true' || true
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${DOSH_BENCH_INCLUDE_MOSH:-0}" = "1" ]; then
|
||||
if ! HOME="$workdir/home-mosh" target/release/dosh-bench \
|
||||
--server bench@127.0.0.1 \
|
||||
|
||||
+65
-33
@@ -40,6 +40,10 @@ struct Args {
|
||||
#[arg(long)]
|
||||
no_cache: bool,
|
||||
#[arg(long)]
|
||||
warm_cache: bool,
|
||||
#[arg(long)]
|
||||
skip_ssh_baseline: bool,
|
||||
#[arg(long)]
|
||||
include_mosh: bool,
|
||||
#[arg(long, default_value = "mosh")]
|
||||
mosh: PathBuf,
|
||||
@@ -51,6 +55,8 @@ struct Args {
|
||||
assert_ssh_plus_ms: Option<f64>,
|
||||
#[arg(long)]
|
||||
assert_mosh_minus_ms: Option<f64>,
|
||||
#[arg(long)]
|
||||
assert_dosh_max_ms: Option<f64>,
|
||||
}
|
||||
|
||||
fn main() -> Result<()> {
|
||||
@@ -72,46 +78,25 @@ fn main() -> Result<()> {
|
||||
} else {
|
||||
None
|
||||
};
|
||||
if args.no_cache && args.warm_cache {
|
||||
return Err(anyhow!("--warm-cache cannot be used with --no-cache"));
|
||||
}
|
||||
let dosh_label = if args.warm_cache {
|
||||
let _ = time_dosh_attach(&client, &args, control_path)?;
|
||||
"dosh_cached_attach_ms"
|
||||
} else {
|
||||
"dosh_attach_ms"
|
||||
};
|
||||
|
||||
for _ in 0..args.iterations.max(1) {
|
||||
if !args.local_auth {
|
||||
if !args.local_auth && !args.skip_ssh_baseline {
|
||||
let mut ssh = Command::new("ssh");
|
||||
add_ssh_options(&mut ssh, &args, control_path);
|
||||
ssh.arg(&args.server).arg("true");
|
||||
ssh_times.push(time_command(&mut ssh)?);
|
||||
}
|
||||
|
||||
let mut cmd = Command::new(&client);
|
||||
cmd.arg("--attach-only")
|
||||
.arg("--session")
|
||||
.arg(&args.session)
|
||||
.arg("--dosh-port")
|
||||
.arg(args.dosh_port.to_string());
|
||||
if let Some(host) = &args.dosh_host {
|
||||
cmd.arg("--dosh-host").arg(host);
|
||||
}
|
||||
if args.local_auth {
|
||||
cmd.arg("--local-auth").arg(&args.server);
|
||||
} else {
|
||||
cmd.arg("--ssh-port")
|
||||
.arg(args.ssh_port.to_string())
|
||||
.arg("--ssh-auth-command")
|
||||
.arg(&args.ssh_auth_command);
|
||||
if args.no_cache {
|
||||
cmd.arg("--no-cache");
|
||||
}
|
||||
if let Some(key) = &args.ssh_key {
|
||||
cmd.arg("--ssh-key").arg(key);
|
||||
}
|
||||
if let Some(known_hosts) = &args.ssh_known_hosts {
|
||||
cmd.arg("--ssh-known-hosts").arg(known_hosts);
|
||||
}
|
||||
if let Some(control_path) = control_path {
|
||||
cmd.arg("--ssh-control-path").arg(control_path);
|
||||
}
|
||||
cmd.arg(&args.server);
|
||||
}
|
||||
dosh_times.push(time_command(&mut cmd)?);
|
||||
dosh_times.push(time_dosh_attach(&client, &args, control_path)?);
|
||||
|
||||
if args.include_mosh {
|
||||
mosh_times.push(time_mosh_in_pty(&args)?);
|
||||
@@ -126,7 +111,7 @@ fn main() -> Result<()> {
|
||||
);
|
||||
}
|
||||
println!(
|
||||
"dosh_attach_ms avg={:.2} samples={:?}",
|
||||
"{dosh_label} avg={:.2} samples={:?}",
|
||||
avg_ms(&dosh_times),
|
||||
dosh_times
|
||||
);
|
||||
@@ -167,9 +152,56 @@ fn main() -> Result<()> {
|
||||
}
|
||||
println!("gate ok: dosh avg {dosh_avg:.2}ms + {margin:.2}ms <= mosh avg {mosh_avg:.2}ms");
|
||||
}
|
||||
if let Some(max_ms) = args.assert_dosh_max_ms {
|
||||
let dosh_avg = avg_ms(&dosh_times);
|
||||
if dosh_avg > max_ms {
|
||||
return Err(anyhow!(
|
||||
"{dosh_label} avg {dosh_avg:.2}ms exceeded max {max_ms:.2}ms"
|
||||
));
|
||||
}
|
||||
println!("gate ok: {dosh_label} avg {dosh_avg:.2}ms <= {max_ms:.2}ms");
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn time_dosh_attach(
|
||||
client: &PathBuf,
|
||||
args: &Args,
|
||||
control_path: Option<&PathBuf>,
|
||||
) -> Result<Duration> {
|
||||
let mut cmd = Command::new(client);
|
||||
cmd.arg("--attach-only")
|
||||
.arg("--session")
|
||||
.arg(&args.session)
|
||||
.arg("--dosh-port")
|
||||
.arg(args.dosh_port.to_string());
|
||||
if let Some(host) = &args.dosh_host {
|
||||
cmd.arg("--dosh-host").arg(host);
|
||||
}
|
||||
if args.local_auth {
|
||||
cmd.arg("--local-auth").arg(&args.server);
|
||||
} else {
|
||||
cmd.arg("--ssh-port")
|
||||
.arg(args.ssh_port.to_string())
|
||||
.arg("--ssh-auth-command")
|
||||
.arg(&args.ssh_auth_command);
|
||||
if args.no_cache {
|
||||
cmd.arg("--no-cache");
|
||||
}
|
||||
if let Some(key) = &args.ssh_key {
|
||||
cmd.arg("--ssh-key").arg(key);
|
||||
}
|
||||
if let Some(known_hosts) = &args.ssh_known_hosts {
|
||||
cmd.arg("--ssh-known-hosts").arg(known_hosts);
|
||||
}
|
||||
if let Some(control_path) = control_path {
|
||||
cmd.arg("--ssh-control-path").arg(control_path);
|
||||
}
|
||||
cmd.arg(&args.server);
|
||||
}
|
||||
time_command(&mut cmd)
|
||||
}
|
||||
|
||||
fn add_ssh_options(cmd: &mut Command, args: &Args, control_path: Option<&PathBuf>) {
|
||||
cmd.arg("-p").arg(args.ssh_port.to_string()).arg("-T");
|
||||
if let Some(key) = &args.ssh_key {
|
||||
|
||||
Reference in New Issue
Block a user