Skip to content

docs(socketwatch): say what the layer timing actually measures - #65

Merged
donislawdev merged 1 commit into
masterfrom
docs/socket-layer-timing-says-what-was-measured
Jul 28, 2026
Merged

docs(socketwatch): say what the layer timing actually measures#65
donislawdev merged 1 commit into
masterfrom
docs/socket-layer-timing-says-what-was-measured

Conversation

@donislawdev

Copy link
Copy Markdown
Owner

Prose only. No behaviour change, no code paths touched, no i18n.

The SOCKET-layer targeting design (#38) is justified by two numbers that came from a 2026-07-22
spike note and were never re-measured. Both are wrong, in different ways - and the conclusion
drawn from the first claimed more than it supports.

Re-measured

Win11, elevated. Three sniff-only handles (SNIFF | RECV_ONLY - cannot drop or modify anything),
opened sequentially, compared on one clock: the QPC stamp WinDivert puts on every event. 10
outbound TCP connections to 8.8.8.8:53.

claim in the code measured
SOCKET_CONNECT ~0.1 ms before the SYN before in 10/10, by 0.018-0.027 ms (median 0.020)
FLOW_ESTABLISHED ~28 ms after the SYN 37.7-41.3 ms after (median 38.7)

What changes, and what does not

The order holds; the margin does not. SOCKET_CONNECT really does precede the SYN every time,
so choosing the SOCKET layer over polling stands and the design is unchanged. But the margin is
five times smaller than the docstring said.

"The race is closed at the source" is cut. Those tens of microseconds are the gap between the
two events at the driver. Whether socketwatch's own handling - thread wake, parse, dict insert -
finishes inside that gap has not been measured, and at 20 us that is no longer self-evident the
way it looked at 100 us. The prose now guarantees ordering and explicitly does not guarantee slack.
That is a weaker claim than before, and it is the one the evidence carries.

The FLOW number was a property of somebody's network. 38.7 ms tracks the round trip to the peer
(ping to the same host on this link: 23-47 ms), because the flow is established once the handshake
completes - so it is recorded as an RTT, not as a constant of the FLOW layer. The reason for
rejecting FLOW is unchanged: it lands after the handshake either way.

Scope

Corrected in socketwatch.py, engine.py::_pid_for, targeting.py, and PROJECT_NOTES (three
places, carried by hand - that file is gitignored).

Deliberately not touched: the ~0.1 ms in model_worker.py, gui/panels/event_log.py and
gui/pages/conns.py. That is the virtualised table's repaint cost - a different measurement that
happens to share a number, and rewriting it would have been the exact mistake this change is
correcting. Historical changelog entries are left as written; they record what was believed then.

Verification

python -m pytest tests -> 709 passed, 0 failed. python smoke_gui.py -> OK. No test guards
prose and none can; what could be done was done - every number now carries its conditions, so the
next session can tell whether it still applies to its machine.

Left open on purpose: whether the first packet of a fresh connection really lands in scope
end-to-end. That is the question the 20 us margin raises, and it needs its own experiment rather
than a sentence.

🤖 Generated with Claude Code

The SOCKET-layer targeting design is justified by two numbers from a 2026-07-22
spike note that were never re-measured. Both are wrong, in different ways, and
the conclusion drawn from the first claimed more than it supports.

Re-measured on 10 outbound TCP connections to 8.8.8.8:53, three sniff-only
handles compared on one clock (the QPC stamp WinDivert puts on every event):

  SOCKET_CONNECT before the SYN : 10/10, by 0.018-0.027 ms  (claimed ~0.1 ms)
  FLOW_ESTABLISHED after the SYN: 37.7-41.3 ms              (claimed ~28 ms)

The ORDER holds, so choosing SOCKET over polling stands. The margin does not: it
is five times smaller than the docstring said. And "the race is closed at the
source" is now cut, because those tens of microseconds are the gap AT THE DRIVER
- whether socketwatch's own thread wake, parse and dict insert fit inside it has
never been measured, and at 20 us that is no longer self-evident the way it
looked at 100 us. Ordering is guaranteed; slack is not.

The FLOW number turned out to be a property of somebody's network rather than of
the FLOW layer: 38.7 ms tracks the round trip to the peer (ping to the same host
here: 23-47 ms), because the flow is established once the handshake completes.
Recorded as such so nobody reads it as a constant. The reason for rejecting FLOW
is unchanged - it lands after the handshake either way.

Deliberately not touched: the ~0.1 ms in model_worker.py, event_log.py and
conns.py is the virtualised table's repaint cost, a different measurement that
happens to share a number. Historical changelog entries stay as written.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@donislawdev
donislawdev merged commit d2fb1a7 into master Jul 28, 2026
7 checks passed
@donislawdev
donislawdev deleted the docs/socket-layer-timing-says-what-was-measured branch July 28, 2026 14:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant