docs(socketwatch): say what the layer timing actually measures - #65
Merged
donislawdev merged 1 commit intoJul 28, 2026
Merged
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
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.
SOCKET_CONNECT~0.1 ms before the SYNFLOW_ESTABLISHED~28 ms after the SYNWhat changes, and what does not
The order holds; the margin does not.
SOCKET_CONNECTreally 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 (threeplaces, carried by hand - that file is gitignored).
Deliberately not touched: the
~0.1 msinmodel_worker.py,gui/panels/event_log.pyandgui/pages/conns.py. That is the virtualised table's repaint cost - a different measurement thathappens 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 guardsprose 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