Skip to content

Comparison to similar tools

A comparison of per-process (per-executable) network and bandwidth monitors on Linux, measuring completeness (is traffic seen and attributed to the right process) and accuracy (are the byte counts correct). It generates known amounts of traffic across many protocols and hard-to-attribute cases, runs each configuration in isolation, and checks the output against tool-independent reference measurements: whether it (a) detected the activity and attributed it to the right process, and (b) measured the right number of bytes.

Nine projects are covered in ten configurations.

24 scenarios × 5 trials on Ubuntu 26.04 (kernel 7.0) on a GCP e2-standard-4 (4 vCPUs, 16 GB), run 2026-08-05. Detection = seen and attributed to the right process; Bandwidth = bytes within ±10% (PASS) / ±25% (PARTIAL) of the reference for the tool's layer. Method, harness, versions, and how to reproduce: the bench/ directory.

Results summary

Each cell counts scenarios (of 24), unweighted; the scenarios are not equally important and the totals are not an overall ranking. N/A marks a missing capability or reference: OpenSnitch does no bandwidth accounting; the BCC utilities and the bpftrace script used here hook TCP only; Sniffnet reports one combined per-program total, so full-duplex scenarios it cannot split by direction are N/A; the loopback scenario has no wire measurement, so tools counting at a packet layer are N/A on its bandwidth.

Tool Detection: PASS / PART / FAIL / N/A Bandwidth: PASS / PART / FAIL / N/A Trial disagreement
Sysdig 24 / 0 / 0 / 0 19 / 0 / 5 / 0 0
picosnitch 23 / 0 / 1 / 0 23 / 0 / 1 / 0 0
Little Snitch 19 / 3 / 2 / 0 16 / 0 / 8 / 0 2
OpenSnitch 19 / 0 / 5 / 0 0 / 0 / 0 / 24 3
bandwhich 15 / 6 / 3 / 0 16 / 1 / 6 / 1 5
BCC tcplife/tcpconnect 14 / 0 / 0 / 10 14 / 0 / 0 / 10 0
bpftrace script 14 / 0 / 0 / 10 14 / 0 / 0 / 10 0
BCC tcptop 14 / 0 / 0 / 10 13 / 0 / 1 / 10 0
Sniffnet 13 / 7 / 4 / 0 18 / 0 / 3 / 3 0
NetHogs 11 / 10 / 3 / 0 17 / 1 / 5 / 1 2

Versions

Read from each installed tool during the run. Pinned entries are built or downloaded at a fixed version by the harness; distro packages are whatever the Ubuntu archive shipped on the run date and are recorded, not pinned.

Tool Version observed Source
Sysdig 0.40.0 distro package (recorded, not pinned)
picosnitch 2.2.1 pinned (PyPI via pipx)
Little Snitch 1.1.0 current release (recorded, not pinned)
OpenSnitch 1.8.0-1 pinned (release .deb)
bandwhich 0.23.1 pinned (release binary)
BCC tcplife/tcpconnect 0.37.0 pinned (built from source tag)
bpftrace script 0.25.0 distro package (recorded, not pinned)
BCC tcptop 0.37.0 pinned (built from source tag)
Sniffnet 1.5.1-1 pinned (release .deb)
NetHogs 0.9.0 pinned (built from source tag)

Observed footprint

Each tool's whole process tree, sampled at 1 Hz across its session under its own capture scope; not a controlled performance comparison. CPU is % of one core (can exceed 100% across cores). PSS (proportional set size) charges each shared page once, split across its sharers.

Tool CPU mean % CPU 95th pct % PSS mean MB PSS peak MB
Sysdig 2.9 9.9 26.9 27.8
picosnitch 0.7 2.9 46.1 46.8
Little Snitch 0.3 1.0 42.7 42.7
OpenSnitch 11.4 106.7 68.4 70.8
bandwhich 2.9 10.0 2.6 2.9
BCC tcplife/tcpconnect 0.0 0.0 276.2 276.3
bpftrace script 0.1 1.0 170.8 170.8
BCC tcptop 0.1 1.0 166.7 166.8
Sniffnet 5.2 20.0 68.1 78.2
NetHogs 0.7 2.0 6.8 7.2

Detection

# Scenario picosnitch NetHogs bandwhich OpenSnitch Sniffnet Little Snitch BCC tcplife/tcpconnect BCC tcptop bpftrace script Sysdig
s01 TCP bulk download (control)
s02 TCP bulk upload
s03 TCP full-duplex up+down
s04 UDP bulk up+down 🟡 ✅*
s05 ICMP echo flood w/ payload 🟡*
s06 UDP/443 bulk 🟡 ✅*
s07 IPv6 TCP transfer
s08 SCTP transfer
s09 Small-packet UDP/53 flood 🟡 ✅*
s10 Raw IP socket (proto 253) egress
s11 Short-lived processes 🟡 🟡 🟡
s12 AF_PACKET raw-frame injection 🟡 🟡 🟡 🟡
s13 io_uring data path 🟡 🟡
s14 sendfile() zero-copy upload
s15 sendmmsg batched UDP 🟡
s16 Loopback-only transfer
s17 In-container (docker) egress 🟡 🟡 🟡 🟡
s18 Low-and-slow drip upload ✅*
s19 Many small TCP connections 🟡
s20 High-rate parallel burst 🟡 🟡 🟡
s21 io_uring download (recv) 🟡 🟡
s22 splice() zero-copy download
s23 recvmmsg batched UDP (recv) 🟡
s24 IPv6 UDP download 🟡

Legend: ✅ PASS · 🟡 PARTIAL · ❌ FAIL · ⬜ N/A · ⚠️ not measured (setup failed or unresolved trial) · * trials disagreed, see the note

Bandwidth accuracy

Scored on bytes reported, independently of attribution: a tool that measured the traffic but bucketed it as unknown is scored here on those bytes, and the detection grid records that miss as PARTIAL.

# Scenario picosnitch NetHogs bandwhich OpenSnitch Sniffnet Little Snitch BCC tcplife/tcpconnect BCC tcptop bpftrace script Sysdig
s01 TCP bulk download (control)
s02 TCP bulk upload
s03 TCP full-duplex up+down
s04 UDP bulk up+down
s05 ICMP echo flood w/ payload ❌*
s06 UDP/443 bulk
s07 IPv6 TCP transfer
s08 SCTP transfer
s09 Small-packet UDP/53 flood
s10 Raw IP socket (proto 253) egress
s11 Short-lived processes ✅*
s12 AF_PACKET raw-frame injection 🟡*
s13 io_uring data path 🟡* ❌* ❌*
s14 sendfile() zero-copy upload ✅*
s15 sendmmsg batched UDP
s16 Loopback-only transfer
s17 In-container (docker) egress
s18 Low-and-slow drip upload
s19 Many small TCP connections
s20 High-rate parallel burst
s21 io_uring download (recv) ❌*
s22 splice() zero-copy download
s23 recvmmsg batched UDP (recv)
s24 IPv6 UDP download

Legend: ✅ PASS · 🟡 PARTIAL · ❌ FAIL · ⬜ N/A · ⚠️ not measured (setup failed or unresolved trial) · * trials disagreed, see the note

Full report