feat: per-process network straggler detection (procfs + eBPF) - #121
Merged
Conversation
Parses /proc/net/snmp and /proc/net/netstat to emit 7 new metrics: tcp_retransmits, tcp_in_segs, tcp_out_segs, tcp_estab_connections, tcp_timeouts, tcp_fast_retrans, tcp_loss_probes. These enable detection of network-induced stragglers that link-level counters alone cannot catch.
shvbsle
force-pushed
the
net-probes
branch
19 times, most recently
from
May 24, 2026 06:54
bda9357 to
cc0dbd9
Compare
eBPF: - kprobe on tcp_rtt_estimator captures raw unsmoothed RTT samples - Reads socket's local port from sk->__sk_common.skc_num - Emits (sport, dport, rtt_us) to ring buffer - Validated: 50ms netem delay → immediate jump to 52ms, instant recovery Architecture refactor: - New ProcessState module replaces watch.rs - Background task refreshes snapshot every 5s (configurable) - Snapshot includes: labels, local_ports, tcp_tx_queue_bytes per PID - Network + eBPF collectors consume snapshot (no direct procfs reads for discovery/ports/tx_queue) - /proc/<pid>/net/snmp still read per-tick by network collector (counters must be fresh for rate computation) - Per-PID RTT attribution via port→pid mapping from snapshot Metrics: - net.tcp_rtt_us: raw RTT per watched process (eBPF, 100ms) - net.tcp_retransmits: per-process counter (procfs, 500ms) - net.tcp_out_segs: per-process counter (procfs, 500ms) - net.tcp_tx_queue_bytes: per-process gauge (snapshot, 5s)
shvbsle
commented
May 24, 2026
shvbsle
commented
May 24, 2026
- Remove net-probes from CI push/docker triggers (main only) - Extract framework label parsing into separate function (extract_framework_labels) that supports multiple conventions: PyTorch (RANK, JOB_NAME), JAX (PROCESS_INDEX), MPI (OMPI_COMM_WORLD_RANK) - Uses entry().or_insert_with() so first match wins (PyTorch takes priority)
shvbsle
marked this pull request as ready for review
May 24, 2026 08:04
- Replace stale per-interface link stats with actual per-process TCP metrics - Document KITTY_WATCH=1 requirement and pod network namespace behavior - Add detection matrix (latency/loss/bandwidth → which metric catches it) - Document eBPF tcp_rtt_estimator approach and why alternatives were rejected - Move implemented features out of "Planned" sections
- Add alpha notice - Add straggler detection section with network (implemented), GPU/compute (planned), and CPU/data pipeline (planned) categories - Show KITTY_WATCH=1 usage in installation section - Update verify section to show what to grep for - Update project structure to include kitty-ebpf
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.
Adds per-process network telemetry to detect network-induced stragglers in distributed training jobs.
What it detects
net.tcp_rtt_ustcp_rtt_estimatornet.tcp_retransmits/proc/<pid>/net/snmpnet.tcp_out_segs+net.tcp_tx_queue_bytes/proc/<pid>/net/snmp+/proc/<pid>/net/tcpHow it works
Kitty watches processes that have
KITTY_WATCH=1in their environment. For each watched process:ProcessStatetask (5s refresh) resolves PIDs, parses/proc/<pid>/net/tcpfor local ports and tx_queue. Optionally extractsRANKandJOB_NAMEfrom environ as metric labels if available (not required — onlyKITTY_WATCH=1is mandatory)./proc/<pid>/net/snmpevery 500ms for monotonic TCP counters.tcp_rtt_estimatorand captures raw (unsmoothed) RTT samples, attributed to the correct process via port matching.Why raw RTT via eBPF
We tried and rejected several alternatives:
/proc/net/tcp: doesn't decay after fault removal (exponential smoothing)tcp_sendmsgduration: sendmsg returns before qdisc delay is appliedtcp_recvmsgduration: data already in socket buffer by the time recvmsg runstcp_rtt_estimatorreceives the raw RTT sample as its second argument (mrtt_us) before any smoothing is applied. This value jumps immediately when latency is introduced and drops immediately when removed.Key design decisions
tcp_rtt_estimatorruns in softirq context (not process context), sobpf_get_current_pid_tgid()returns an unrelated process. Instead, the BPF program reads the socket's local port fromstruct sock, and userspace maps port→pid by discovering NCCL connections from/proc/<pid>/net/tcp(refreshed every 5s in the snapshot). No hardcoded ports — they're whatever NCCL allocates at runtime.ProcessStateis a shared snapshot that both network and eBPF collectors consume — no duplicated procfs reads/proc/<pid>/net/snmpis read per-tick (500ms) because counters must be fresh for rate computation; everything else is cached in the 5s snapshotValidation
Tested with
kfault inject-oneon a 4-node GPT-2 DDP training job (g4dn.xlarge, 1x T4 per node):tcp_rtt_ustcp_retransmitstcp_out_segsUsage
Add to training pod env:
Metrics appear at
:9100/metricslabeled with{pid, rank, job}.