From 3d377e0628dad54ebf3b1a8147b4e818059aa997 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 19:32:36 +0100 Subject: [PATCH 1/4] issues: the scoreboard's unrecorded gaps, and the T14's durable writes across five boots The 2026-10-28 scoreboard compares ToyOS at 069cbbeb8 against each bench's Linux as installed: 4 boots against 5 runs, interleaved (evidence branch scoreboard-2026-10-28). Each row ToyOS loses with no owning record now has one, with its figures, an owner and an exit: - a small message's round trip over a native connection (ipc.reqrep.8, 2.04x on the T14); - the futex ping-pong (2.01x and 1.37x on the T14); - tmpfs metadata calls (fs.mem open_close, stat, rename, mkdir_rmdir, 4.1-6.5x on the T14); - process and thread spawn, and the all-CPU build (up to 3.7x on the T14, and 2.3x for j16 on the AMD); - small memcpy on the AMD (64 B at 0.61 of Linux's); - no loopback, so osbench net measures nothing; - std's yield_now, which yields nothing. The T14 durable-write record takes all five boots: 2 of 5 ran persist six times slower throughout and a third turned slow partway, with nothing in the logs to tell them apart. It gets a slug that says so, which #1097 had on its branch after it merged. Co-Authored-By: Claude Opus 5.5 --- ...sts-toyos-up-to-twice-linuxs-on-the-t14.md | 31 +++++++++++++ ...ench-runs-at-up-to-six-tenths-of-linuxs.md | 31 +++++++++++++ ...onnection-costs-twice-linuxs-on-the-t14.md | 30 +++++++++++++ ...call-costs-toyos-up-to-six-times-linuxs.md | 35 +++++++++++++++ ...ompares-toyos-with-linux-on-one-machine.md | 3 +- ...oyos-up-to-four-times-linuxs-on-the-t14.md | 44 +++++++++++++++++++ .../std-yield-now-on-toyos-yields-nothing.md | 25 +++++++++++ ...nvme-run-six-times-slower-in-some-boots.md | 38 ++++++++++++++++ ...4s-nvme-took-1-to-6-ms-across-two-boots.md | 32 -------------- ...oopback-so-osbench-net-measures-nothing.md | 31 +++++++++++++ 10 files changed, 267 insertions(+), 33 deletions(-) create mode 100644 issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md create mode 100644 issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md create mode 100644 issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md create mode 100644 issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md create mode 100644 issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md create mode 100644 issues/std-yield-now-on-toyos-yields-nothing.md create mode 100644 issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md delete mode 100644 issues/toyos-durable-writes-on-the-t14s-nvme-took-1-to-6-ms-across-two-boots.md create mode 100644 issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md diff --git a/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md b/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md new file mode 100644 index 00000000000..baf7d003783 --- /dev/null +++ b/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md @@ -0,0 +1,31 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A futex ping-pong costs ToyOS up to twice Linux's on the T14 + +`osbench sched`'s `pingpong.futex.*` passes a turn between two threads by +futex wait and wake, on one CPU (`same_cpu`) and across cores +(`cross_core`). Each sample is one round trip as the pinger sees it. +The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `pingpong.futex.same_cpu` | 4,580 ns (10.1%) | 2,279 ns (4.4%) | 5,015 ns (31.3%) | 6,248 ns (27.1%) | +| `pingpong.futex.cross_core` | 4,574 ns (2.5%) | 3,341 ns (0.9%) | 5,662 ns (26.7%) | 9,864 ns (43.5%) | + +On the T14 ToyOS loses both, 2.01x on one CPU and 1.37x across cores, and +both resolve. On the AMD ToyOS resolves better. That bench's Linux timed +two of five runs through the HPET, at 1.2 µs a timestamp. The pipe +ping-pong rows show the same T14 shape (`pingpong.pipe.same_cpu` 1.37x, +`cross_core` 1.83x). Where the round trip's time goes, the wait, the wake or +the switch, is unmeasured. + +**Exit**: `pingpong.futex.*` within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured to its parts +and justified. + +**Owner**: the kernel's futex and wake path (`kernel/src/sched/futex.rs`, +`kernel/src/sched/`). diff --git a/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md b/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md new file mode 100644 index 00000000000..4aabc38e2b6 --- /dev/null +++ b/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md @@ -0,0 +1,31 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A small memcpy on the AMD bench runs at up to six tenths of Linux's + +`osbench mem`'s `mem.memcpy.` copies a buffer of that size with each +system's own `memcpy`. On ToyOS that is `sdk/libc`'s, which hands every copy +to the architecture's `copy_forward`; on Linux it is the static musl build's. +The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | AMD ToyOS | AMD Linux | T14 ToyOS | T14 Linux | +|---|---|---|---|---| +| `mem.memcpy.64` | 3,942 MB/s (0.7%) | 6,492 MB/s (1.7%) | 18,507 MB/s (6.9%) | 6,226 MB/s (1.2%) | +| `mem.memcpy.256` | 14,493 MB/s (0.7%) | 16,158 MB/s (1.7%) | 29,720 MB/s (11.1%) | 24,932 MB/s (1.5%) | +| `mem.memcpy.262144` | 25,696 MB/s (45.1%) | 36,472 MB/s (3.4%) | 55,722 MB/s (0.0%) | 55,634 MB/s (0.1%) | + +On the AMD (Ryzen 7 4800U) ToyOS loses 64 bytes at 0.61 of Linux's, 256 at +0.90 and 256 KiB at 0.70, each resolved. On the T14 (i5-1135G7) ToyOS wins +64 bytes threefold and matches at 256 KiB. One copy routine is fast on one +CPU and slow on the other at the same sizes. Its strategy at each size on +Zen 2, a `rep movsb` start-up or otherwise, is not yet read against AMD's +optimization guide. The 256 KiB row's 45% ToyOS range is also unexplained. + +**Exit**: `mem.memcpy.*` within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured and +justified against the vendors' guidance. + +**Owner**: userland's copy (`sdk/libc/src/memory.rs` and its `arch`). diff --git a/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md b/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md new file mode 100644 index 00000000000..c4c2b5c238f --- /dev/null +++ b/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md @@ -0,0 +1,30 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A small message's round trip over a native connection costs twice Linux's on the T14 + +`osbench ipc`'s `ipc.reqrep.8` sends 8 bytes to a server process and waits +for its 8-byte answer, over ToyOS's native connection and over a Unix stream +socket on Linux. `ipc.reqrep_handle.8` also moves a handle with each request. +The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `ipc.reqrep.8` | 7,184 ns (1.9%) | 3,515 ns (22.1%) | 7,324 ns (25.3%) | 13,829 ns (58.1%) | +| `ipc.reqrep_handle.8` | 8,789 ns (2.5%) | 7,260 ns (3.7%) | 8,887 ns (23.4%) | 21,077 ns (42.7%) | + +On the T14 ToyOS loses both rows, 2.04x and 1.21x, and both resolve. On the +AMD it does not, but there two of five Linux runs timed through the HPET, +whose 1.2 µs a timestamp is in every Linux sample. The bulk-copy rows +(`ipc.reqrep.4096`, `65536`) are +`issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. What the +8-byte round trip spends its time on is unmeasured. + +**Exit**: `ipc.reqrep.8` and `ipc.reqrep_handle.8` within Linux's on both +benches in a labelled current-state comparison, or each remaining difference +measured to its parts and justified. + +**Owner**: native IPC (`sdk/toyos/src/ipc.rs` and the kernel's message path). diff --git a/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md new file mode 100644 index 00000000000..4dea2758b7a --- /dev/null +++ b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md @@ -0,0 +1,35 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A tmpfs metadata call costs ToyOS up to six times Linux's + +`osbench files` runs the same operations under each system's kernel memory +filesystem: ToyOS's `/tmp`, which the kernel serves through syscalls, and +Linux's `/dev/shm`, tmpfs through the VFS. No file server is involved. +The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `fs.mem.open_close` | 7,291 ns (7.7%) | 1,114 ns (8.1%) | 6,157 ns (0.8%) | 2,946 ns (48.4%) | +| `fs.mem.stat` | 3,115 ns (5.3%) | 584 ns (2.6%) | 2,616 ns (1.1%) | 1,513 ns (90.7%) | +| `fs.mem.rename` | 7,374 ns (6.3%) | 1,624 ns (2.3%) | 6,282 ns (1.1%) | 4,538 ns (35.7%) | +| `fs.mem.mkdir_rmdir` | 9,011 ns (9.1%) | 2,213 ns (1.5%) | 7,705 ns (3.1%) | 6,702 ns (23.3%) | + +On the T14 ToyOS loses all four, 4.1x to 6.5x, and all resolve. On the AMD +it loses `open_close` (2.1x) and `rename` (1.4x), both resolved, and reads +worse unresolved on the other two. That bench's Linux spreads are wide +because two of its five runs timed through the HPET. The listing +(`fs.mem.readdir.1000`) is +`issues/a-listing-still-scans-the-whole-mount.md`'s, and the sequential copies +are `issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. What a +tmpfs path lookup and metadata call spend their time on is unmeasured. + +**Exit**: these four rows within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured to its parts +and justified. + +**Owner**: the kernel's tmpfs and VFS (`kernel/src/tmpfs.rs`, +`kernel/src/vfs.rs`). diff --git a/issues/no-published-run-compares-toyos-with-linux-on-one-machine.md b/issues/no-published-run-compares-toyos-with-linux-on-one-machine.md index 723a6c4f1cd..c07acd6f323 100644 --- a/issues/no-published-run-compares-toyos-with-linux-on-one-machine.md +++ b/issues/no-published-run-compares-toyos-with-linux-on-one-machine.md @@ -82,7 +82,8 @@ comparison until it can: AX200, are measured under Linux alone. - **USB, NVMe and cpuidle identity**: their owners serve no program that reads them. -- **Loopback** (`net.*`): netstack refuses 127/8 as a destination. +- **Loopback** (`net.*`): netstack refuses 127/8 as a destination + (`issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md`). **Exit**: both systems' outputs on the T14 and the AMD bench published in evidence, Linux's run before the T14's wipe. Linux's outputs are a goal diff --git a/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md new file mode 100644 index 00000000000..12dd83780a0 --- /dev/null +++ b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md @@ -0,0 +1,44 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# Spawning a process costs ToyOS up to four times Linux's on the T14 + +`osbench`'s spawn rows spawn a program, wait for it, and time the whole: +`proc.spawn_wait.*` by std's `Command`, `proc.posix_spawn_wait.*` by C's +`posix_spawn` and `waitpid`, and `process.spawn_wait` this program itself. +`tiny` is a minimal program, `large` the same with 32 MiB of unread data, and +`std` the osbench binary. `thread.spawn_join.*` creates and joins an empty +thread. `work.build_shaped.j` compresses 256 files, one child process +each, as many at once as there are CPUs. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `proc.spawn_wait.large` | 202,300 ns (13.0%) | 54,906 ns (3.0%) | 170,284 ns (18.2%) | 273,444 ns (10.2%) | +| `proc.posix_spawn_wait.std` | 451,798 ns (1.7%) | 169,630 ns (2.1%) | 504,838 ns (6.8%) | 327,668 ns (158.1%) | +| `process.spawn_wait` | 452,918 ns (4.7%) | 179,133 ns (6.0%) | 534,832 ns (3.8%) | 911,540 ns (64.2%) | +| `proc.posix_spawn_wait.tiny` | 55,722 ns (10.1%) | 43,698 ns (2.4%) | 75,015 ns (4.2%) | 92,704 ns (150.0%) | +| `thread.spawn_join.stack64k` | 28,562 ns (0.9%) | 23,441 ns (1.1%) | 40,322 ns (3.3%) | 65,844 ns (22.2%) | +| `thread.spawn_join` | 28,144 ns (1.0%) | 25,040 ns (2.6%) | 41,094 ns (4.4%) | 72,607 ns (34.6%) | +| `work.build_shaped.j` | 166.2 ms (2.4%), j8 | 99.1 ms (1.2%), j8 | 270.7 ms (1.0%), j16 | 116.7 ms (13.4%), j16 | + +On the T14 ToyOS loses every row here, 1.1x to 3.7x, each resolved. The cost +grows with the program's size: 3.7x for `large` and 2.5 to 2.7x for the osbench +binary, against 1.3x for `tiny`. The AMD's spawns and thread creations read +better for ToyOS, but two of five Linux runs there timed through the HPET. +The all-CPU build loses on both benches: 1.7x on the T14 and 2.3x on the AMD, +where ToyOS's one-at-a-time build (`j1`) is faster than Linux's on both. What a +spawn spends on the program's size, and why the parallel build loses where +the serial one wins, is unmeasured. +`issues/idle-cpus-enter-the-c-states-cst-names.md` records the T14's `j1` +under deep idle. + +**Exit**: these rows within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured to its parts +and justified. + +**Owner**: process creation (`kernel/src/process.rs`, `kernel/src/elf/`, the +SDK's spawn and `sdk/libc`'s `posix_spawn`) and, for the parallel build, the +scheduler (`kernel/src/sched/`). diff --git a/issues/std-yield-now-on-toyos-yields-nothing.md b/issues/std-yield-now-on-toyos-yields-nothing.md new file mode 100644 index 00000000000..669409c606e --- /dev/null +++ b/issues/std-yield-now-on-toyos-yields-nothing.md @@ -0,0 +1,25 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# std's `yield_now` on ToyOS yields nothing + +ToyOS has no yield syscall, and its std's `thread::yield_now` is a spin-loop +hint (`sdk/std/sys/thread.rs`). A Rust program that yields to let another +runnable thread go keeps its CPU instead, and spin-wait loops written against +`yield_now` behave unlike they do on every other platform. `osbench`'s +`time.yield` therefore reports `unsupported` on ToyOS rather than time a hint +against Linux's `sched_yield`. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 Linux | AMD Linux | ToyOS | +|---|---|---|---| +| `time.yield` | 190,677 ps (0.6%) | 552,167 ps (1.9%) | unsupported, all 4 boots on both benches | + +**Exit**: a yield that gives the CPU to another runnable thread of the +caller's priority, std's `yield_now` on it, and `time.yield` measured on +ToyOS within Linux's on both benches. + +**Owner**: the scheduler's syscall surface (`kernel/src/sched/`, `sdk/abi`) +and ToyOS's std (`sdk/std/sys/thread.rs`). diff --git a/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md b/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md new file mode 100644 index 00000000000..2faa58b46d2 --- /dev/null +++ b/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md @@ -0,0 +1,38 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# ToyOS's durable writes on the T14's NVMe run six times slower in some boots + +On the T14 (SK hynix BC501, volatile write cache present, so ToyOS's NVMe +driver issues Flush), five boots of PR #1097's storage code on 2026-10-28, +all off the internal NVMe with DATA on it, read these p50s: + +| boot | `fsync_clean` | `write_4k_fsync` | `append_4k_fsync` | `create_fsync_unlink` | `seq_write_fsync` | +|---|---|---|---|---|---| +| c8f3fbfb0 (16:08) | 3.02 ms | 6.13 ms | 6.18 ms | 6.87 ms | 162 MB/s | +| 069cbbeb8 (16:47) | 0.46 ms | 1.10 ms | 1.01 ms | 1.17 ms | 347 MB/s | +| 069cbbeb8 (17:31) | 3.42 ms | 6.65 ms | 6.85 ms | 5.05 ms | 149 MB/s | +| 069cbbeb8 (17:39) | 0.50 ms | 1.08 ms | 1.04 ms | 7.10 ms | 167 MB/s | +| 069cbbeb8 (17:48) | 0.58 ms | 1.08 ms | 1.09 ms | 1.23 ms | 311 MB/s | + +The bench's Linux, five runs interleaved with these on ext4 on the same +NVMe, read `write_4k_fsync` and `append_4k_fsync` at 0.81 to 1.20 ms in +every run. Two of the five ToyOS boots ran slow through all of `persist`. +A third turned slow partway, between `append_4k_fsync` and +`create_fsync_unlink`. No change to the NVMe driver, the block service, the +file server or the DATA format lies between the two heads. The boots' NVMe +and DATA log lines do not tell the slow ones apart, and the cause is +unknown. A fast boot's clean fsync, a superblock write and a Flush, takes +0.46 to 0.58 ms where Linux's takes 23 µs +(`issues/a-clean-fsync-on-data-writes-the-superblock-and-flushes-the-disk.md`). +The figures are evidence branch `scoreboard-2026-10-28`'s and PR #1097's. + +**Exit**: repeated boots on the T14 read ToyOS's `persist.write_4k_fsync` +within Linux's every time, or the boots that do not are explained by a +measured cause. + +**Owner**: the NVMe driver (`system/nvme/`) and the DATA volume's commit +(`lib/bcachefs/src/fs.rs`). diff --git a/issues/toyos-durable-writes-on-the-t14s-nvme-took-1-to-6-ms-across-two-boots.md b/issues/toyos-durable-writes-on-the-t14s-nvme-took-1-to-6-ms-across-two-boots.md deleted file mode 100644 index fb0341082f4..00000000000 --- a/issues/toyos-durable-writes-on-the-t14s-nvme-took-1-to-6-ms-across-two-boots.md +++ /dev/null @@ -1,32 +0,0 @@ ---- -status: open -kind: defect -opened: 2026-10-28 ---- - -# ToyOS's durable writes on the T14's NVMe took 1 to 6 ms across two boots - -On the T14 (SK hynix BC501, volatile write cache present, so ToyOS's NVMe -driver issues Flush), two boots of PR #1097, both off the internal NVMe with -DATA on it, read these p50s. Linux is two runs on ext4 on the same NVMe in -each validation: - -| row | ToyOS, c8f3fbfb0 | ToyOS, 069cbbeb8 | Linux (both validations) | -|---|---|---|---| -| `persist.fsync_clean` | 3,019,602 ns | 464,505 ns | 22,970 to 23,012 ns | -| `persist.write_4k_fsync` | 6,125,947 ns | 1,099,737 ns | 811,313 to 1,035,997 ns | -| `persist.append_4k_fsync` | 6,182,133 ns | 1,012,768 ns | 796,449 to 1,200,332 ns | -| `persist.seq_write_fsync` | 162 MB/s | 347 MB/s | 527 to 598 MB/s | - -No change to the NVMe driver, the block service, the file server or the -DATA format lies between the two heads; the second rebased onto #1095's -boot path, and both booted off the NVMe. Why one boot's durable writes cost -six times the other's is unknown. The clean fsync's remaining 20x, a -superblock write and a Flush where Linux's clean fsync takes 23 µs, is -`issues/a-clean-fsync-on-data-writes-the-superblock-and-flushes-the-disk.md`. - -**Exit**: repeated boots on the T14 read ToyOS's `persist.write_4k_fsync` -within Linux's, or the boots that do not are explained by a measured cause. - -**Owner**: the NVMe driver (`system/nvme/`) and the DATA volume's commit -(`lib/bcachefs/src/fs.rs`). diff --git a/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md new file mode 100644 index 00000000000..134964f463d --- /dev/null +++ b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md @@ -0,0 +1,31 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# ToyOS has no loopback, so `osbench net` measures nothing + +netstack carries no loopback. Its UDP refuses a loopback destination and a +send to its own address by name (`system/netstack/udp/src/lib.rs`'s +`unusable`: `Counter::SendLoopback`, `SendToSelf`). `osbench net`, which +measures TCP and UDP between two local processes over 127.0.0.1, reports all +five rows unsupported on ToyOS without trying them, so how netstack's TCP +answers a connect to 127/8 is unread. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +| row | T14 Linux | AMD Linux | +|---|---|---| +| `net.tcp.connect_accept_close` | 20,913 ns (1.0%) | 49,002 ns (59.0%) | +| `net.tcp.reqrep.64` | 8,935 ns (8.5%) | 27,241 ns (30.8%) | +| `net.tcp.stream.65536` | 6,719 MB/s (2.3%) | 2,894 MB/s (25.1%) | +| `net.udp.reqrep.64` | 7,287 ns (2.3%) | 22,642 ns (78.6%) | + +ToyOS: `unsupported` in all 4 boots on both benches. A program that talks to +itself or a sibling over 127.0.0.1, as many servers and tests do, cannot +run unchanged on ToyOS. + +**Exit**: netstack carries a loopback path, `osbench net` attempts its rows +on ToyOS, and they are within Linux's on both benches in a labelled +current-state comparison. + +**Owner**: netstack (`system/netstack/`). From 153e85d0748be0300983bc07667ede901c80eabf Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 23:03:25 +0100 Subject: [PATCH 2/4] review r1: the gap records say what the per-run data and the code show The tmpfs record's exit is the migrated /tmp of storage track step 9 and it carries all eight fs.mem rows. The ipc, spawn and two-thread ping-pong records read the AMD's Linux per run, its first three runs on the TSC and its last two on the HPET, rather than hedging on the clocksource. The futex record becomes the two-thread ping-pong record and takes the pipe rows. The durable-write record gives each Linux set's range and exits on every persist row. The loopback record states the route refusal, the refused listen and the UDP refusals from the code, and counts the connect answered ERR_NOT_CONNECTED as part of the defect. The memcpy record cites the ERMS and memset records and is renamed for what its title claims; the memset record no longer calls memcpy unmeasured. The shootdown and hot-paths records carry the munmap and bandwidth rows they own. Co-Authored-By: Claude Opus 5.5 --- ...sts-toyos-up-to-twice-linuxs-on-the-t14.md | 31 -------- ...et-on-x86-64-costs-a-rep-stosb-start-up.md | 2 +- ...ns-at-as-little-as-six-tenths-of-linuxs.md | 41 +++++++++++ ...ench-runs-at-up-to-six-tenths-of-linuxs.md | 31 -------- ...onnection-costs-twice-linuxs-on-the-t14.md | 20 ++++-- ...eaches-only-the-cpus-that-ran-the-space.md | 5 ++ ...call-costs-toyos-up-to-six-times-linuxs.md | 59 ++++++++++----- ...sts-toyos-up-to-twice-linuxs-on-the-t14.md | 45 ++++++++++++ ...oyos-up-to-four-times-linuxs-on-the-t14.md | 71 +++++++++++++------ .../std-yield-now-on-toyos-yields-nothing.md | 9 ++- ...nvme-run-six-times-slower-in-some-boots.md | 18 +++-- ...oopback-so-osbench-net-measures-nothing.md | 61 ++++++++++------ ...y-hot-paths-are-slower-than-2-mib-pages.md | 6 ++ 13 files changed, 264 insertions(+), 135 deletions(-) delete mode 100644 issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md create mode 100644 issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md delete mode 100644 issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md create mode 100644 issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md diff --git a/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md b/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md deleted file mode 100644 index baf7d003783..00000000000 --- a/issues/a-futex-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -status: open -kind: defect -opened: 2026-10-28 ---- - -# A futex ping-pong costs ToyOS up to twice Linux's on the T14 - -`osbench sched`'s `pingpong.futex.*` passes a turn between two threads by -futex wait and wake, on one CPU (`same_cpu`) and across cores -(`cross_core`). Each sample is one round trip as the pinger sees it. -The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): - -| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | -|---|---|---|---|---| -| `pingpong.futex.same_cpu` | 4,580 ns (10.1%) | 2,279 ns (4.4%) | 5,015 ns (31.3%) | 6,248 ns (27.1%) | -| `pingpong.futex.cross_core` | 4,574 ns (2.5%) | 3,341 ns (0.9%) | 5,662 ns (26.7%) | 9,864 ns (43.5%) | - -On the T14 ToyOS loses both, 2.01x on one CPU and 1.37x across cores, and -both resolve. On the AMD ToyOS resolves better. That bench's Linux timed -two of five runs through the HPET, at 1.2 µs a timestamp. The pipe -ping-pong rows show the same T14 shape (`pingpong.pipe.same_cpu` 1.37x, -`cross_core` 1.83x). Where the round trip's time goes, the wait, the wake or -the switch, is unmeasured. - -**Exit**: `pingpong.futex.*` within Linux's on both benches in a labelled -current-state comparison, or each remaining difference measured to its parts -and justified. - -**Owner**: the kernel's futex and wake path (`kernel/src/sched/futex.rs`, -`kernel/src/sched/`). diff --git a/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md b/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md index 1ed1b3caf05..757d7b39872 100644 --- a/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md +++ b/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md @@ -24,4 +24,4 @@ any program makes pays the instruction's start-up. - That wipe costs more than `rep stosb` on long records. reject at 16 KiB reads 0.98 against ring on the T14 (0.76 with the `memset`) and 1.11–1.14 on the AMD bench (1.03). - Evidence for those readings: the r4 judge logs linked above. -**Exit.** `fill` takes a short-length path, or selects by the fast short `rep stosb` feature where the CPU has it. The crate's workarounds then go: the refusal returns to `fill(0)`, and `block.rs`'s header drops its reason. `memcpy`'s `rep movsb` may share the cost; it is unmeasured. The T14 reads a 0 B and a 64 B `memset` within a few nanoseconds of a store loop's. The kernel's counterpart is `issues/kernel-forward-copies-and-fills-are-one-rep-movsb-or-stosb-on-every-cpu.md`. +**Exit.** `fill` takes a short-length path, or selects by the fast short `rep stosb` feature where the CPU has it. The crate's workarounds then go: the refusal returns to `fill(0)`, and `block.rs`'s header drops its reason. `memcpy`'s `rep movsb` shares it on the AMD bench: `mem.memcpy.64` reads 0.61 of Linux's there (`issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md`). The T14 reads a 0 B and a 64 B `memset` within a few nanoseconds of a store loop's. The kernel's counterpart is `issues/kernel-forward-copies-and-fills-are-one-rep-movsb-or-stosb-on-every-cpu.md`. diff --git a/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md b/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md new file mode 100644 index 00000000000..a45158e560a --- /dev/null +++ b/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md @@ -0,0 +1,41 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A small memcpy on the AMD bench runs at as little as six tenths of Linux's + +`osbench mem`'s `mem.memcpy.` copies a buffer of that size with each +system's own `memcpy`. On ToyOS that is `sdk/libc`'s, whose `copy_forward` is +one `rep movsb` at every length (`sdk/libc/src/arch/x86_64.rs`). On Linux it +is the static musl build's. + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. + +| row | AMD ToyOS | AMD Linux | T14 ToyOS | T14 Linux | +|---|---|---|---|---| +| `mem.memcpy.64` | 3,942 MB/s (0.7%) | 6,492 MB/s (1.7%) | 18,507 MB/s (6.9%) | 6,226 MB/s (1.2%) | +| `mem.memcpy.256` | 14,493 MB/s (0.7%) | 16,158 MB/s (1.7%) | 29,720 MB/s (11.1%) | 24,932 MB/s (1.5%) | +| `mem.memcpy.16384` | 75,330 MB/s (1.2%) | 73,707 MB/s (3.0%) | 185,364 MB/s (0.3%) | 201,387 MB/s (17.9%) | +| `mem.memcpy.262144` | 25,696 MB/s (45.1%) | 36,472 MB/s (3.4%) | 55,722 MB/s (0.0%) | 55,634 MB/s (0.1%) | +| `mem.memcpy.67108864` | 6,140 MB/s (0.5%) | 6,302 MB/s (4.5%) | 9,257 MB/s (0.6%) | 9,677 MB/s (1.2%) | + +On the AMD (Ryzen 7 4800U) ToyOS loses 64 bytes at 0.61 of Linux's, 256 at +0.90 and 256 KiB at 0.70, each resolved. Zen 2 lacks ERMS +(`issues/kernel-forward-copies-and-fills-are-one-rep-movsb-or-stosb-on-every-cpu.md`), +and a `rep movsb` start-up is the cost +`issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md` records for +`memset`. This row is that record's `memcpy` measurement. On the T14 +(i5-1135G7) ToyOS wins 64 bytes threefold. It loses 16 KiB (1.09x) and +64 MiB (1.05x), both resolved, and matches at 256 KiB. The 256 KiB row's 45% +ToyOS range on the AMD is unexplained. + +**Exit**: `mem.memcpy.*` within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured and +justified against the vendors' guidance. + +**Owner**: userland's copy (`sdk/libc/src/memory.rs` and its `arch`). diff --git a/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md b/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md deleted file mode 100644 index 4aabc38e2b6..00000000000 --- a/issues/a-small-memcpy-on-the-amd-bench-runs-at-up-to-six-tenths-of-linuxs.md +++ /dev/null @@ -1,31 +0,0 @@ ---- -status: open -kind: defect -opened: 2026-10-28 ---- - -# A small memcpy on the AMD bench runs at up to six tenths of Linux's - -`osbench mem`'s `mem.memcpy.` copies a buffer of that size with each -system's own `memcpy`. On ToyOS that is `sdk/libc`'s, which hands every copy -to the architecture's `copy_forward`; on Linux it is the static musl build's. -The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): - -| row | AMD ToyOS | AMD Linux | T14 ToyOS | T14 Linux | -|---|---|---|---|---| -| `mem.memcpy.64` | 3,942 MB/s (0.7%) | 6,492 MB/s (1.7%) | 18,507 MB/s (6.9%) | 6,226 MB/s (1.2%) | -| `mem.memcpy.256` | 14,493 MB/s (0.7%) | 16,158 MB/s (1.7%) | 29,720 MB/s (11.1%) | 24,932 MB/s (1.5%) | -| `mem.memcpy.262144` | 25,696 MB/s (45.1%) | 36,472 MB/s (3.4%) | 55,722 MB/s (0.0%) | 55,634 MB/s (0.1%) | - -On the AMD (Ryzen 7 4800U) ToyOS loses 64 bytes at 0.61 of Linux's, 256 at -0.90 and 256 KiB at 0.70, each resolved. On the T14 (i5-1135G7) ToyOS wins -64 bytes threefold and matches at 256 KiB. One copy routine is fast on one -CPU and slow on the other at the same sizes. Its strategy at each size on -Zen 2, a `rep movsb` start-up or otherwise, is not yet read against AMD's -optimization guide. The 256 KiB row's 45% ToyOS range is also unexplained. - -**Exit**: `mem.memcpy.*` within Linux's on both benches in a labelled -current-state comparison, or each remaining difference measured and -justified against the vendors' guidance. - -**Owner**: userland's copy (`sdk/libc/src/memory.rs` and its `arch`). diff --git a/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md b/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md index c4c2b5c238f..cd61c5a15ac 100644 --- a/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md +++ b/issues/a-small-message-round-trip-over-a-native-connection-costs-twice-linuxs-on-the-t14.md @@ -9,7 +9,12 @@ opened: 2026-10-28 `osbench ipc`'s `ipc.reqrep.8` sends 8 bytes to a server process and waits for its 8-byte answer, over ToyOS's native connection and over a Unix stream socket on Linux. `ipc.reqrep_handle.8` also moves a handle with each request. -The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. The AMD's Linux runs 1 to 3 timed through the TSC and 4 +and 5 through the HPET, at 1.2 µs a timestamp. | row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | |---|---|---|---|---| @@ -17,11 +22,16 @@ The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe aga | `ipc.reqrep_handle.8` | 8,789 ns (2.5%) | 7,260 ns (3.7%) | 8,887 ns (23.4%) | 21,077 ns (42.7%) | On the T14 ToyOS loses both rows, 2.04x and 1.21x, and both resolve. On the -AMD it does not, but there two of five Linux runs timed through the HPET, -whose 1.2 µs a timestamp is in every Linux sample. The bulk-copy rows -(`ipc.reqrep.4096`, `65536`) are +AMD it does not lose: +- `reqrep_handle.8` resolves ToyOS better (0.42x). ToyOS's slowest boot, + 9,959 ns, beats every TSC Linux run, 20,238 to 21,099 ns. +- `reqrep.8` is unresolved. Linux's runs spread within the TSC runs + themselves, 7,684, 14,983 and 15,719 ns, and the HPET runs read 13,829 and + 10,551, so the median is an HPET run's. + +The bulk-copy rows (`ipc.reqrep.4096`, `65536`) are `issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. What the -8-byte round trip spends its time on is unmeasured. +T14's 8-byte round trip spends its time on is unmeasured. **Exit**: `ipc.reqrep.8` and `ipc.reqrep_handle.8` within Linux's on both benches in a labelled current-state comparison, or each remaining difference diff --git a/issues/a-tlb-shootdown-reaches-only-the-cpus-that-ran-the-space.md b/issues/a-tlb-shootdown-reaches-only-the-cpus-that-ran-the-space.md index e75186e5b49..e36fbdd2985 100644 --- a/issues/a-tlb-shootdown-reaches-only-the-cpus-that-ran-the-space.md +++ b/issues/a-tlb-shootdown-reaches-only-the-cpus-that-ran-the-space.md @@ -31,5 +31,10 @@ another space runs there, and faults touching the page again after the initiator unmapped it meanwhile. The TCG model has no PCID (`build/arch.rs`), so only metal can show a switched-out CPU's entries. +In the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`) the +T14 lost `mem.munmap_part.4k` at 1.22x Linux's (1,558 against 1,280 ns) and +`mem.munmap_touched_remote.4k` at 1.32x (3,028 against 2,290 ns), each +resolved; the AMD won both. + **Exit**: that case, on each proving machine with PCID, red with the flush on entry removed; and the T14's munmap and `vm_protect` figures against Linux. diff --git a/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md index 4dea2758b7a..a4080f2ca2f 100644 --- a/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md +++ b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md @@ -6,10 +6,15 @@ opened: 2026-10-28 # A tmpfs metadata call costs ToyOS up to six times Linux's -`osbench files` runs the same operations under each system's kernel memory -filesystem: ToyOS's `/tmp`, which the kernel serves through syscalls, and -Linux's `/dev/shm`, tmpfs through the VFS. No file server is involved. -The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): +`osbench files` runs the same operations under each system's memory +filesystem: ToyOS's `/tmp`, which the kernel serves through syscalls today, +and Linux's `/dev/shm`, tmpfs through the VFS. + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. The AMD's Linux runs 1 to 3 timed through the TSC and 4 +and 5 through the HPET, at 1.2 µs a timestamp. | row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | |---|---|---|---|---| @@ -17,19 +22,35 @@ The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe aga | `fs.mem.stat` | 3,115 ns (5.3%) | 584 ns (2.6%) | 2,616 ns (1.1%) | 1,513 ns (90.7%) | | `fs.mem.rename` | 7,374 ns (6.3%) | 1,624 ns (2.3%) | 6,282 ns (1.1%) | 4,538 ns (35.7%) | | `fs.mem.mkdir_rmdir` | 9,011 ns (9.1%) | 2,213 ns (1.5%) | 7,705 ns (3.1%) | 6,702 ns (23.3%) | +| `fs.mem.tree.100` | 1,505,195 ns (4.1%) | 548,925 ns (1.1%) | 1,384,280 ns (1.3%) | 1,457,995 ns (2.6%) | +| `fs.mem.create_write_unlink` | 12,832 ns (4.7%) | 4,715 ns (2.1%) | 10,801 ns (0.6%) | 12,743 ns (13.7%) | +| `fs.mem.write_4k_at` | 1,237 ns (4.0%) | 625 ns (5.0%) | 1,563 ns (7.7%) | 1,823 ns (61.0%) | +| `fs.mem.read_4k_at` | 1,222 ns (2.3%) | 710 ns (4.5%) | 1,422 ns (3.5%) | 1,403 ns (70.8%) | + + +On the T14 ToyOS loses all eight, 1.7x to 6.5x, each resolved. On the AMD it +loses `open_close` (2.1x) and `rename` (1.4x), both resolved, wins +`tree.100`, `create_write_unlink` and `write_4k_at`, and is unresolved on the +other three. There the +HPET does fit: Linux's TSC runs read `open_close` at 2.9 µs and its HPET runs +at 4.3 µs, so its spread is the clocksource's. The listing +(`fs.mem.readdir.1000`) is `issues/a-listing-still-scans-the-whole-mount.md`'s, +and the sequential copies are +`issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. + +**The kernel's tmpfs is not where this is fixed.** Step 9 of +`issues/the-kernel-is-small-interrupts-post-and-threads-wait.md`, under the +owner's rulings of 2026-09-25 and 2026-10-03, deletes `tmpfs.rs`, +`fs_rename.rs`, `file_cache.rs` and `vfs.rs`, and moves `/tmp` to +userland per session. An `fs.mem` call then becomes a file server request, +which costs 3 to 12 times a kernel file call today +(`issues/a-file-server-request-costs-three-to-twelve-times-a-kernel-file-call.md`). +So the move makes this gap larger, unless the file server's round trip +shrinks first. + +**Exit**: once `/tmp` is served from userland, these eight rows within +Linux's on both benches in a labelled current-state comparison, or each +remaining difference measured to its parts and justified. -On the T14 ToyOS loses all four, 4.1x to 6.5x, and all resolve. On the AMD -it loses `open_close` (2.1x) and `rename` (1.4x), both resolved, and reads -worse unresolved on the other two. That bench's Linux spreads are wide -because two of its five runs timed through the HPET. The listing -(`fs.mem.readdir.1000`) is -`issues/a-listing-still-scans-the-whole-mount.md`'s, and the sequential copies -are `issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. What a -tmpfs path lookup and metadata call spend their time on is unmeasured. - -**Exit**: these four rows within Linux's on both benches in a labelled -current-state comparison, or each remaining difference measured to its parts -and justified. - -**Owner**: the kernel's tmpfs and VFS (`kernel/src/tmpfs.rs`, -`kernel/src/vfs.rs`). +**Owner**: whatever serves `/tmp` through step 9's migration. Until then, +nothing in the kernel's tmpfs is owed this work. diff --git a/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md new file mode 100644 index 00000000000..e73db058e13 --- /dev/null +++ b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md @@ -0,0 +1,45 @@ +--- +status: open +kind: defect +opened: 2026-10-28 +--- + +# A two-thread ping-pong costs ToyOS up to twice Linux's on the T14 + +`osbench sched`'s `pingpong.*` passes a turn between two threads, by futex +wait and wake (`futex`) and by a pipe's write and read (`pipe`). It runs on +one CPU (`same_cpu`) and across cores (`cross_core`). Each sample is one +round trip as the pinger sees it. + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. The AMD's Linux runs 1 to 3 timed through the TSC and 4 +and 5 through the HPET, at 1.2 µs a timestamp. + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `pingpong.futex.same_cpu` | 4,580 ns (10.1%) | 2,279 ns (4.4%) | 5,015 ns (31.3%) | 6,248 ns (27.1%) | +| `pingpong.futex.cross_core` | 4,574 ns (2.5%) | 3,341 ns (0.9%) | 5,662 ns (26.7%) | 9,864 ns (43.5%) | +| `pingpong.pipe.same_cpu` | 6,186 ns (1.3%) | 4,504 ns (54.4%) | 5,656 ns (1.2%) | 7,739 ns (24.9%) | +| `pingpong.pipe.cross_core` | 6,802 ns (7.1%) | 3,712 ns (6.0%) | 5,746 ns (30.5%) | 15,021 ns (57.8%) | + +On the T14 ToyOS loses all four, 1.37x to 2.01x, each resolved. On the AMD +ToyOS is faster in all four, and against Linux's TSC runs alone too: the +futex rows read 6,141 to 6,248 ns (`same_cpu`) and 9,648 to 9,864 ns +(`cross_core`) there, both above ToyOS's medians. So the T14's gap is no +clocksource's. Where its round trip's time goes, the wait, the wake or the +switch, is unmeasured. + +#1074 has since changed the pipe on main, so the `pipe` rows' current state +is owed a new reading. +The scheduler's pair-wake records bear on both kinds: +`issues/a-wake-whose-waker-parks-next-is-forwarded-to-an-idle-cpu.md` and +`issues/an-ordinary-wake-posted-on-its-own-cpu-waits-for-that-cpus-next-pass.md`. + +**Exit**: `pingpong.*` within Linux's on both benches in a labelled +current-state comparison, or each remaining difference measured to its parts +and justified. + +**Owner**: the kernel's futex and wake path (`kernel/src/sched/futex.rs`, +`kernel/src/sched/`), and the pipe (`kernel/src/pipe.rs`) for its rows. diff --git a/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md index 12dd83780a0..45341a6597e 100644 --- a/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md +++ b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md @@ -6,32 +6,63 @@ opened: 2026-10-28 # Spawning a process costs ToyOS up to four times Linux's on the T14 -`osbench`'s spawn rows spawn a program, wait for it, and time the whole: -`proc.spawn_wait.*` by std's `Command`, `proc.posix_spawn_wait.*` by C's -`posix_spawn` and `waitpid`, and `process.spawn_wait` this program itself. -`tiny` is a minimal program, `large` the same with 32 MiB of unread data, and -`std` the osbench binary. `thread.spawn_join.*` creates and joins an empty -thread. `work.build_shaped.j` compresses 256 files, one child process -each, as many at once as there are CPUs. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): +`osbench`'s spawn rows spawn a program, wait for it, and time the whole. +`proc.spawn_wait.*` uses std's `Command`, `proc.posix_spawn_wait.*` C's +`posix_spawn` and `waitpid`, and `process.spawn_wait` spawns osbench itself. +`tiny` is a minimal program written to `/tmp`, `large` the same with 32 MiB +of data it never reads, and `std` the osbench binary. `thread.spawn_join.*` +creates and joins an empty thread. `work.build_shaped.j` compresses 256 +files, one child process each, as many at once as there are CPUs. + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. The AMD's Linux runs 1 to 3 timed through the TSC and 4 +and 5 through the HPET, at 1.2 µs a timestamp. | row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | |---|---|---|---|---| +| `proc.spawn_wait.tiny` | 52,548 ns (19.8%) | 52,094 ns (1.2%) | 69,724 ns (11.8%) | 266,663 ns (64.7%) | | `proc.spawn_wait.large` | 202,300 ns (13.0%) | 54,906 ns (3.0%) | 170,284 ns (18.2%) | 273,444 ns (10.2%) | +| `proc.posix_spawn_wait.tiny` | 55,722 ns (10.1%) | 43,698 ns (2.4%) | 75,015 ns (4.2%) | 92,704 ns (150.0%) | | `proc.posix_spawn_wait.std` | 451,798 ns (1.7%) | 169,630 ns (2.1%) | 504,838 ns (6.8%) | 327,668 ns (158.1%) | | `process.spawn_wait` | 452,918 ns (4.7%) | 179,133 ns (6.0%) | 534,832 ns (3.8%) | 911,540 ns (64.2%) | -| `proc.posix_spawn_wait.tiny` | 55,722 ns (10.1%) | 43,698 ns (2.4%) | 75,015 ns (4.2%) | 92,704 ns (150.0%) | -| `thread.spawn_join.stack64k` | 28,562 ns (0.9%) | 23,441 ns (1.1%) | 40,322 ns (3.3%) | 65,844 ns (22.2%) | | `thread.spawn_join` | 28,144 ns (1.0%) | 25,040 ns (2.6%) | 41,094 ns (4.4%) | 72,607 ns (34.6%) | -| `work.build_shaped.j` | 166.2 ms (2.4%), j8 | 99.1 ms (1.2%), j8 | 270.7 ms (1.0%), j16 | 116.7 ms (13.4%), j16 | - -On the T14 ToyOS loses every row here, 1.1x to 3.7x, each resolved. The cost -grows with the program's size: 3.7x for `large` and 2.5 to 2.7x for the osbench -binary, against 1.3x for `tiny`. The AMD's spawns and thread creations read -better for ToyOS, but two of five Linux runs there timed through the HPET. -The all-CPU build loses on both benches: 1.7x on the T14 and 2.3x on the AMD, -where ToyOS's one-at-a-time build (`j1`) is faster than Linux's on both. What a -spawn spends on the program's size, and why the parallel build loses where -the serial one wins, is unmeasured. +| `thread.spawn_join.stack64k` | 28,562 ns (0.9%) | 23,441 ns (1.1%) | 40,322 ns (3.3%) | 65,844 ns (22.2%) | + +| row | ToyOS | Linux | +|---|---|---| +| T14 `work.build_shaped.j8` | 166,245,528 ns (2.4%) | 99,148,404 ns (1.2%) | +| AMD `work.build_shaped.j16` | 270,675,582 ns (1.0%) | 116,739,823 ns (13.4%) | + +**On the T14** ToyOS loses every spawn and thread row but one. The +like-for-like pair is std's `Command` with the two programs: `tiny` reads +1.01x, unresolved, and `large` 3.68x, resolved. So what costs ToyOS on that +bench is what `large` adds, its 32 MiB in `/tmp` (8,192 pages), not the +spawn itself. `posix_spawn` of the osbench binary reads 2.66x and +`process.spawn_wait` 2.53x. + +**On the AMD** ToyOS resolves better on `spawn_wait.large`, +`posix_spawn_wait.tiny`, `spawn_wait.tiny` and every thread row, and stays +better against Linux's TSC runs alone (`large`: Linux 259 to 273 µs, ToyOS +155 to 186 µs). It reads better, unresolved, on `process.spawn_wait`, and +1.54x worse, unresolved, on `posix_spawn_wait.std`. +Linux's spreads there are its own: bimodal within the TSC runs +(`posix_spawn_wait.std` run 2 reads 740 µs), and a 1.2 µs timestamp is under +1% of a spawn. + +**The all-CPU build loses on both benches**, 1.68x on the T14 (`j8`) and +2.32x on the AMD (`j16`), where ToyOS's one-at-a-time build (`j1`) beats +Linux's on both. + +What `large` exercises is recorded. A spawn from a `/tmp` file snapshots it, +taking a reference to each resident page under the file cache's lock and 16 +bytes a page (`issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`, +"Spawn"), and shared text is stage 5 of +`issues/process-memory-in-4-kib-pages-still-copies-each-programs-text.md`. +This record adds the measured cost of that mechanism against Linux, the +osbench binary's spawn on the T14, the thread rows, and the parallel build, +whose loss where the serial build wins is unmeasured. `issues/idle-cpus-enter-the-c-states-cst-names.md` records the T14's `j1` under deep idle. @@ -40,5 +71,5 @@ current-state comparison, or each remaining difference measured to its parts and justified. **Owner**: process creation (`kernel/src/process.rs`, `kernel/src/elf/`, the -SDK's spawn and `sdk/libc`'s `posix_spawn`) and, for the parallel build, the +SDK's spawn and `sdk/libc/src/spawn.rs`) and, for the parallel build, the scheduler (`kernel/src/sched/`). diff --git a/issues/std-yield-now-on-toyos-yields-nothing.md b/issues/std-yield-now-on-toyos-yields-nothing.md index 669409c606e..9b44422dcad 100644 --- a/issues/std-yield-now-on-toyos-yields-nothing.md +++ b/issues/std-yield-now-on-toyos-yields-nothing.md @@ -11,14 +11,19 @@ hint (`sdk/std/sys/thread.rs`). A Rust program that yields to let another runnable thread go keeps its CPU instead, and spin-wait loops written against `yield_now` behave unlike they do on every other platform. `osbench`'s `time.yield` therefore reports `unsupported` on ToyOS rather than time a hint -against Linux's `sched_yield`. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): +against Linux's `sched_yield`. + +From the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`): +ToyOS at 069cbbeb8, four boots off the internal NVMe, against five runs of +each bench's Linux as installed, interleaved. A cell is the p50 with its +run-to-run range. | row | T14 Linux | AMD Linux | ToyOS | |---|---|---|---| | `time.yield` | 190,677 ps (0.6%) | 552,167 ps (1.9%) | unsupported, all 4 boots on both benches | **Exit**: a yield that gives the CPU to another runnable thread of the -caller's priority, std's `yield_now` on it, and `time.yield` measured on +caller's band, std's `yield_now` on it, and `time.yield` measured on ToyOS within Linux's on both benches. **Owner**: the scheduler's syscall surface (`kernel/src/sched/`, `sdk/abi`) diff --git a/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md b/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md index 2faa58b46d2..dac95da6200 100644 --- a/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md +++ b/issues/toyos-durable-writes-on-the-t14s-nvme-run-six-times-slower-in-some-boots.md @@ -18,9 +18,14 @@ all off the internal NVMe with DATA on it, read these p50s: | 069cbbeb8 (17:39) | 0.50 ms | 1.08 ms | 1.04 ms | 7.10 ms | 167 MB/s | | 069cbbeb8 (17:48) | 0.58 ms | 1.08 ms | 1.09 ms | 1.23 ms | 311 MB/s | -The bench's Linux, five runs interleaved with these on ext4 on the same -NVMe, read `write_4k_fsync` and `append_4k_fsync` at 0.81 to 1.20 ms in -every run. Two of the five ToyOS boots ran slow through all of `persist`. +The bench's Linux, on ext4 on the same NVMe, read these rows in the runs +interleaved with each set of boots. The c8f3fbfb0 boot had its own +validation's two Linux runs: `write_4k_fsync` 0.81 to 1.01 ms, +`append_4k_fsync` 0.80 to 1.04 ms, `create_fsync_unlink` 0.86 to 0.93 ms, and +`seq_write_fsync` 587 to 598 MB/s. The four 069cbbeb8 boots were interleaved +with five Linux runs: `write_4k_fsync` 0.99 to 1.04 ms, `append_4k_fsync` 0.83 +to 1.25 ms, `create_fsync_unlink` 0.94 to 0.98 ms, and `seq_write_fsync` 486 to +600 MB/s. Two of the five ToyOS boots ran slow through all of `persist`. A third turned slow partway, between `append_4k_fsync` and `create_fsync_unlink`. No change to the NVMe driver, the block service, the file server or the DATA format lies between the two heads. The boots' NVMe @@ -30,9 +35,10 @@ unknown. A fast boot's clean fsync, a superblock write and a Flush, takes (`issues/a-clean-fsync-on-data-writes-the-superblock-and-flushes-the-disk.md`). The figures are evidence branch `scoreboard-2026-10-28`'s and PR #1097's. -**Exit**: repeated boots on the T14 read ToyOS's `persist.write_4k_fsync` -within Linux's every time, or the boots that do not are explained by a -measured cause. +**Exit**: repeated boots on the T14 read every durable `persist` row +(`write_4k_fsync`, `append_4k_fsync`, `create_fsync_unlink` and +`seq_write_fsync`) within Linux's, in every boot and for the whole of each +boot's run. Or the slow mode is explained by a measured cause. **Owner**: the NVMe driver (`system/nvme/`) and the DATA volume's commit (`lib/bcachefs/src/fs.rs`). diff --git a/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md index 134964f463d..649af1a350a 100644 --- a/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md +++ b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md @@ -6,26 +6,47 @@ opened: 2026-10-28 # ToyOS has no loopback, so `osbench net` measures nothing -netstack carries no loopback. Its UDP refuses a loopback destination and a -send to its own address by name (`system/netstack/udp/src/lib.rs`'s -`unusable`: `Counter::SendLoopback`, `SendToSelf`). `osbench net`, which -measures TCP and UDP between two local processes over 127.0.0.1, reports all -five rows unsupported on ToyOS without trying them, so how netstack's TCP -answers a connect to 127/8 is unread. The 2026-10-28 scoreboard (ToyOS at 069cbbeb8, 4 boots off the internal NVMe against 5 runs of each bench's Linux as installed, interleaved; p50s, with the run-to-run range; evidence branch `scoreboard-2026-10-28`): - -| row | T14 Linux | AMD Linux | -|---|---|---| -| `net.tcp.connect_accept_close` | 20,913 ns (1.0%) | 49,002 ns (59.0%) | -| `net.tcp.reqrep.64` | 8,935 ns (8.5%) | 27,241 ns (30.8%) | -| `net.tcp.stream.65536` | 6,719 MB/s (2.3%) | 2,894 MB/s (25.1%) | -| `net.udp.reqrep.64` | 7,287 ns (2.3%) | 22,642 ns (78.6%) | - -ToyOS: `unsupported` in all 4 boots on both benches. A program that talks to -itself or a sibling over 127.0.0.1, as many servers and tests do, cannot -run unchanged on ToyOS. - -**Exit**: netstack carries a loopback path, `osbench net` attempts its rows -on ToyOS, and they are within Linux's on both benches in a labelled +netstack treats 127/8 as a destination that never exists (`is_martian`, +`system/netstack/wire/src/addr.rs`), and so does each of its paths: +- **TCP connect.** `shard::connect` asks the route first, and the route + refuses a martian (`system/netstack/ip/src/route.rs`, + `Counter::RouteInvalidDestination`) before it would match the host's own + address. +- **TCP listen.** `shard::listen` refuses an address the host does not hold, + 127.0.0.1 among them, as `NotLocal`, answered `ERR_INVALID_INPUT` + (`system/netstack/src/serve.rs`). So `TcpListener::bind("127.0.0.1:0")`, + a loopback program's first call, fails. +- **UDP.** `unusable` refuses a loopback destination and a send to the + host's own address by name (`system/netstack/udp/src/lib.rs`, + `Counter::SendLoopback`, `SendToSelf`). +- **Tests.** The unit tests hold these refusals: TCP's + `s_hs_035_connect_needs_a_unicast_remote` (LOCALHOST among them) and UDP's + `s_udp_us_003_only_an_assigned_address_binds`. + +**The connect's refusal is misreported.** `serve.rs`'s `connect_refused` +answers any route refusal `ERR_NOT_CONNECTED`, whose contract is "a machine +with no address or no route yet … which clears when a lease lands". For +127/8 it never clears. A program connecting to localhost is told it is +waiting for a lease, not that the destination is refused. + +`osbench net` measures TCP and UDP between two local processes over +127.0.0.1, and reports all five rows unsupported on ToyOS without trying. From +the 2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`), five +runs of each bench's Linux: + +| row | T14 ToyOS | T14 Linux | AMD ToyOS | AMD Linux | +|---|---|---|---|---| +| `net.tcp.connect_accept_close` | unsupported | 20,913 ns (1.0%) | unsupported | 49,002 ns (59.0%) | +| `net.tcp.reqrep.64` | unsupported | 8,935 ns (8.5%) | unsupported | 27,241 ns (30.8%) | +| `net.tcp.stream.65536` | unsupported | 6,719 MB/s (2.3%) | unsupported | 2,894 MB/s (25.1%) | +| `net.udp.reqrep.64` | unsupported | 7,287 ns (2.3%) | unsupported | 22,642 ns (78.6%) | + +A program that talks to itself or a sibling over 127.0.0.1, as many servers +and tests do, cannot run unchanged on ToyOS. + +**Exit**: netstack carries a loopback path, and a connect it still refuses is +answered by what it is, not as a missing lease. `osbench net` attempts its +rows on ToyOS, and they are within Linux's on both benches in a labelled current-state comparison. **Owner**: netstack (`system/netstack/`). diff --git a/issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md b/issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md index 497c7d6c12d..958c3edfa36 100644 --- a/issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md +++ b/issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md @@ -82,6 +82,12 @@ The copies (`fs.tmp`, `ipc`, `pipe`) point at the user-copy path above. "With runs" is `a75abd3f6` against `b48c7dd9d` on the T14, one run each; `6d826e313` gave 500, 521 and 132,434 for the first three rows. +`mem.bw.copy` streams two 64 MiB buffers it asks to be huge. In the +2026-10-28 scoreboard (evidence branch `scoreboard-2026-10-28`) Linux gave +131,072 KiB of huge pages and ToyOS none; ToyOS read 0.95 of Linux's on the +T14 (6,651 against 6,992 MB/s) and 0.98 on the AMD (8,352 against 8,550), +each resolved worse. + `mem.realloc_grow` no longer copies. std and libc map a block of 256 KiB or more on its own (`sdk/libc/src/mapped.rs`) and grow it by `vm_remap`, which moves pages. On the T14 at 204243e7f, `1m_256m` took 45.9 us, its last From 2cb987b3a71c62d733ab75746e671b3e020fe681 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 23:10:57 +0100 Subject: [PATCH 3/4] issues: the ping-pong record cites the pipe record that reads #1074's rows Co-Authored-By: Claude Opus 5.5 --- ...d-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md index e73db058e13..826686a0827 100644 --- a/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md +++ b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md @@ -31,8 +31,10 @@ futex rows read 6,141 to 6,248 ns (`same_cpu`) and 9,648 to 9,864 ns clocksource's. Where its round trip's time goes, the wait, the wake or the switch, is unmeasured. -#1074 has since changed the pipe on main, so the `pipe` rows' current state -is owed a new reading. +#1074 has since changed the pipe on main and reads `pingpong.pipe.*` lower +on its head than its base +(`issues/a-64-kib-pipe-write-is-two-percent-below-the-two-mebibyte-ring.md`), +so the `pipe` rows' current state against Linux is owed a new reading. The scheduler's pair-wake records bear on both kinds: `issues/a-wake-whose-waker-parks-next-is-forwarded-to-an-idle-cpu.md` and `issues/an-ordinary-wake-posted-on-its-own-cpu-waits-for-that-cpus-next-pass.md`. From f2e72a543b4e3060a108389232b6c61c6a79e106 Mon Sep 17 00:00:00 2001 From: japabu Date: Wed, 28 Oct 2026 23:33:32 +0100 Subject: [PATCH 4/4] review r2: the spawn and memset records claim only what their rows show The spawn record scopes its conclusion to the std Command pair; the memset record says memcpy may share the start-up. The ping-pong record states the T14 Linux clocksource instead of inferring it from the AMD, the loopback record cites the route test a 127/8 connect reaches, and the memcpy record notes the sweep's huge-page difference. Co-Authored-By: Claude Opus 5.5 --- .../a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md | 2 +- ...e-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md | 5 ++++- ...mpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md | 6 ++---- ...d-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md | 4 ++-- ...rocess-costs-toyos-up-to-four-times-linuxs-on-the-t14.md | 6 +++--- ...toyos-has-no-loopback-so-osbench-net-measures-nothing.md | 5 +++-- 6 files changed, 15 insertions(+), 13 deletions(-) diff --git a/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md b/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md index 757d7b39872..295d960a85f 100644 --- a/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md +++ b/issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md @@ -24,4 +24,4 @@ any program makes pays the instruction's start-up. - That wipe costs more than `rep stosb` on long records. reject at 16 KiB reads 0.98 against ring on the T14 (0.76 with the `memset`) and 1.11–1.14 on the AMD bench (1.03). - Evidence for those readings: the r4 judge logs linked above. -**Exit.** `fill` takes a short-length path, or selects by the fast short `rep stosb` feature where the CPU has it. The crate's workarounds then go: the refusal returns to `fill(0)`, and `block.rs`'s header drops its reason. `memcpy`'s `rep movsb` shares it on the AMD bench: `mem.memcpy.64` reads 0.61 of Linux's there (`issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md`). The T14 reads a 0 B and a 64 B `memset` within a few nanoseconds of a store loop's. The kernel's counterpart is `issues/kernel-forward-copies-and-fills-are-one-rep-movsb-or-stosb-on-every-cpu.md`. +**Exit.** `fill` takes a short-length path, or selects by the fast short `rep stosb` feature where the CPU has it. The crate's workarounds then go: the refusal returns to `fill(0)`, and `block.rs`'s header drops its reason. `memcpy`'s `rep movsb` may share it: `mem.memcpy.64` reads 0.61 of Linux's on the AMD bench (`issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md`). The T14 reads a 0 B and a 64 B `memset` within a few nanoseconds of a store loop's. The kernel's counterpart is `issues/kernel-forward-copies-and-fills-are-one-rep-movsb-or-stosb-on-every-cpu.md`. diff --git a/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md b/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md index a45158e560a..d4c2897dd73 100644 --- a/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md +++ b/issues/a-small-memcpy-on-the-amd-bench-runs-at-as-little-as-six-tenths-of-linuxs.md @@ -31,7 +31,10 @@ and a `rep movsb` start-up is the cost `issues/a-short-memset-on-x86-64-costs-a-rep-stosb-start-up.md` records for `memset`. This row is that record's `memcpy` measurement. On the T14 (i5-1135G7) ToyOS wins 64 bytes threefold. It loses 16 KiB (1.09x) and -64 MiB (1.05x), both resolved, and matches at 256 KiB. The 256 KiB row's 45% +64 MiB (1.05x), both resolved, and matches at 256 KiB. The sweep asks for +huge pages, which Linux gives and ToyOS does not; the 64 MiB row's 0.95 of +Linux's equals `mem.bw.copy`'s under the same difference +(`issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`). The 256 KiB row's 45% ToyOS range on the AMD is unexplained. **Exit**: `mem.memcpy.*` within Linux's on both benches in a labelled diff --git a/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md index a4080f2ca2f..30f31aa391b 100644 --- a/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md +++ b/issues/a-tmpfs-metadata-call-costs-toyos-up-to-six-times-linuxs.md @@ -27,13 +27,11 @@ and 5 through the HPET, at 1.2 µs a timestamp. | `fs.mem.write_4k_at` | 1,237 ns (4.0%) | 625 ns (5.0%) | 1,563 ns (7.7%) | 1,823 ns (61.0%) | | `fs.mem.read_4k_at` | 1,222 ns (2.3%) | 710 ns (4.5%) | 1,422 ns (3.5%) | 1,403 ns (70.8%) | - On the T14 ToyOS loses all eight, 1.7x to 6.5x, each resolved. On the AMD it loses `open_close` (2.1x) and `rename` (1.4x), both resolved, wins `tree.100`, `create_write_unlink` and `write_4k_at`, and is unresolved on the -other three. There the -HPET does fit: Linux's TSC runs read `open_close` at 2.9 µs and its HPET runs -at 4.3 µs, so its spread is the clocksource's. The listing +other three. There the HPET explains Linux's spread: its TSC runs read +`open_close` at 2.9 µs and its HPET runs at 4.3 µs. The listing (`fs.mem.readdir.1000`) is `issues/a-listing-still-scans-the-whole-mount.md`'s, and the sequential copies are `issues/user-memory-hot-paths-are-slower-than-2-mib-pages.md`'s. diff --git a/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md index 826686a0827..dc3a01c71b1 100644 --- a/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md +++ b/issues/a-two-thread-ping-pong-costs-toyos-up-to-twice-linuxs-on-the-t14.md @@ -27,8 +27,8 @@ and 5 through the HPET, at 1.2 µs a timestamp. On the T14 ToyOS loses all four, 1.37x to 2.01x, each resolved. On the AMD ToyOS is faster in all four, and against Linux's TSC runs alone too: the futex rows read 6,141 to 6,248 ns (`same_cpu`) and 9,648 to 9,864 ns -(`cross_core`) there, both above ToyOS's medians. So the T14's gap is no -clocksource's. Where its round trip's time goes, the wait, the wake or the +(`cross_core`) there, both above ToyOS's medians. The T14's Linux timed every +run through the TSC. Where its round trip's time goes, the wait, the wake or the switch, is unmeasured. #1074 has since changed the pipe on main and reads `pingpong.pipe.*` lower diff --git a/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md index 45341a6597e..40f2d220f3a 100644 --- a/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md +++ b/issues/spawning-a-process-costs-toyos-up-to-four-times-linuxs-on-the-t14.md @@ -37,9 +37,9 @@ and 5 through the HPET, at 1.2 µs a timestamp. **On the T14** ToyOS loses every spawn and thread row but one. The like-for-like pair is std's `Command` with the two programs: `tiny` reads -1.01x, unresolved, and `large` 3.68x, resolved. So what costs ToyOS on that -bench is what `large` adds, its 32 MiB in `/tmp` (8,192 pages), not the -spawn itself. `posix_spawn` of the osbench binary reads 2.66x and +1.01x, unresolved, and `large` 3.68x, resolved. Under `Command`, then, what +costs ToyOS on that bench is what `large` adds, its 32 MiB in `/tmp` +(8,192 pages). `posix_spawn` of the osbench binary reads 2.66x and `process.spawn_wait` 2.53x. **On the AMD** ToyOS resolves better on `spawn_wait.large`, diff --git a/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md index 649af1a350a..e302991bafa 100644 --- a/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md +++ b/issues/toyos-has-no-loopback-so-osbench-net-measures-nothing.md @@ -19,8 +19,9 @@ netstack treats 127/8 as a destination that never exists (`is_martian`, - **UDP.** `unusable` refuses a loopback destination and a send to the host's own address by name (`system/netstack/udp/src/lib.rs`, `Counter::SendLoopback`, `SendToSelf`). -- **Tests.** The unit tests hold these refusals: TCP's - `s_hs_035_connect_needs_a_unicast_remote` (LOCALHOST among them) and UDP's +- **Tests.** The unit tests hold these refusals: the route's + `s_ip_rte_006_invalid_and_local_destinations` (127.0.0.1 is + `RouteInvalidDestination`, `system/netstack/ip/tests/addr.rs`) and UDP's `s_udp_us_003_only_an_assigned_address_binds`. **The connect's refusal is misreported.** `serve.rs`'s `connect_refused`