How Does KEIBIDROP Compare?

Benchmarking Against croc, wormhole, LocalSend, and scp

10 min read | KEIBIDROP Series

We built croc, wormhole-william, and a Go reimplementation of LocalSend's protocol from source and benchmarked them head-to-head against KEIBIDROP on the same machine, same loopback, same methodology. KEIBIDROP's encrypted gRPC (442 MB/s) is 2.9x faster than croc (153 MB/s) and 3.5x faster than wormhole (126 MB/s). LocalSend's protocol is faster (612-704 MB/s) because it's a simple HTTPS POST with near-zero framing -- but the real Dart/Flutter app drops to 50-120 MB/s. The gap between KEIBIDROP and LocalSend's protocol is mostly gRPC overhead (28%), not encryption.

Lab Setup

All benchmarks ran on the same machine, over localhost loopback, to isolate software overhead (encryption, protocol framing, I/O layers) from network variability.

CPUIntel Core i7-9750H @ 2.60GHz (AES-NI)
RAM32 GB
OSmacOS 26.3 (x86_64)
Go1.24.3
DiskAPPLE SSD (NVMe)

Methodology: Each tool transfers a pre-allocated random file from sender to receiver over localhost. Wall-clock time is measured from "start send" to "file verified on disk at receiver." Tests run sequentially -- one tool at a time, no contention. Files are pre-generated (not counted in timing).

KEIBIDROP uses ::1 loopback, in-process mock relay, gRPC over ChaCha20-Poly1305 encrypted TCP. The FUSE benchmark additionally routes reads through the macFUSE kernel module.

croc runs with a local relay on 127.0.0.1:9009 (no internet). Encryption: XSalsa20-Poly1305 with PAKE key exchange. Built from github.com/schollz/croc v10.4.2.

wormhole-william uses the public mailbox server for SPAKE2 signaling (adds ~2-3s setup latency). Data transfer is direct localhost. Built from github.com/psanford/wormhole-william.

LocalSend protocol -- we reimplemented LocalSend's v2 transfer protocol in Go: HTTPS POST with self-signed TLS, binary body streaming. Same endpoints and flow as the real app (prepare-upload to upload). This measures the raw protocol speed, not the Dart/Flutter app. Source: github.com/localsend/localsend.

scp uses the system SSH daemon over localhost. Encryption is AES-256-GCM (negotiated by SSH, hardware-accelerated).

cp is the raw disk baseline -- no encryption, no network stack.

Results

Tool1 MB10 MB100 MB1 GB
cp (baseline)20 MB/s208 MB/s1177 MB/s2183 MB/s
scp (SSH)15 MB/s175 MB/s1087 MB/s2306 MB/s
LocalSend AES-GCM175 MB/s440 MB/s617 MB/s704 MB/s
LocalSend ChaCha20130 MB/s368 MB/s537 MB/s612 MB/s
KEIBIDROP gRPC52 MB/s64 MB/s175 MB/s442 MB/s
KEIBIDROP FUSE52 MB/s64 MB/s175 MB/s233 MB/s
croc (local relay)2.7 MB/s24 MB/s113 MB/s153 MB/s
wormhole-william0.4 MB/s3.6 MB/s31 MB/s126 MB/s

(KEIBIDROP numbers from go test benchmarks on the same machine, same loopback. All other tools built from source and benchmarked identically.)

Isolating the Cipher: AES-GCM vs ChaCha20-Poly1305

To get an honest comparison, we ran the LocalSend protocol benchmark twice: once with Go's default TLS 1.3 (which negotiates AES-128-GCM and uses AES-NI hardware), and once forcing ChaCha20-Poly1305 -- the same cipher KEIBIDROP uses.

LocalSend protocol (1 GB)CipherSpeed
TLS 1.3 defaultAES-128-GCM (AES-NI hardware)704 MB/s
TLS 1.2 forcedChaCha20-Poly1305 (software)612 MB/s

The AES-NI advantage is 13% -- real but not the main story. Both ciphers are fast on this CPU. The bigger factor is protocol framing.

Where the Gap Actually Is

With the same cipher (ChaCha20), the comparison becomes:

Tool (ChaCha20-Poly1305, 1 GB)SpeedDifference
LocalSend protocol (HTTPS POST)612 MB/sbaseline
KEIBIDROP gRPC442 MB/s-28%
KEIBIDROP FUSE233 MB/s-62%

The 28% gap between LocalSend protocol and KEIBIDROP gRPC comes from three sources:

These are different tools solving different problems. LocalSend is optimized for one-shot local transfers. KEIBIDROP maintains a persistent P2P connection with resume, notifications, and a virtual filesystem. The 28% overhead is the cost of those features.

What the Numbers Tell Us

Small files (1-10 MB): Protocol setup overhead dominates. Croc spends ~400ms on PAKE key exchange and relay handshake. Wormhole spends ~2.7s on SPAKE2 through the public mailbox server. scp spends ~50ms on SSH handshake. LocalSend protocol is lightweight -- an HTTPS POST with a small JSON handshake (~8ms for 1MB). KEIBIDROP has zero per-transfer setup -- the connection is already established.

Large files (1 GB): Croc tops out at 153 MB/s -- its relay-forwarding architecture adds a hop even on localhost. Wormhole hits 126 MB/s. KEIBIDROP's gRPC hits 442 MB/s, 2.9x faster than croc. LocalSend's protocol reaches 612-704 MB/s because a single HTTPS POST body has minimal framing overhead.

FUSE overhead: KEIBIDROP through FUSE (233 MB/s) vs raw gRPC (442 MB/s) shows the 48% overhead of kernel-to-userspace context switches. This is inherent to any FUSE filesystem. Even with FUSE, it's 1.5x faster than croc and 1.8x faster than wormhole. The tradeoff is that FUSE gives you a mounted filesystem where you can run git, open files in editors, etc.

Why scp Appears "Faster"

scp at 2.3 GB/s looks impossibly fast -- faster than cp. Both hit the OS page cache on localhost. The file was recently written during test setup, so it's already in RAM. scp over localhost sends through the loopback socket with AES-256-GCM at near-zero cost (AES-NI). On a real network with wire speed limits, the difference disappears.

A Note on LocalSend

Our benchmark implements LocalSend's v2 protocol in Go -- same HTTPS endpoints, same TLS, same binary POST body. At 612-704 MB/s, the protocol is well-designed. We did not benchmark the actual LocalSend Dart/Flutter app, so we cannot make direct speed claims about it. User reports online suggest 50-120 MB/s on wired LAN, but we haven't verified this ourselves. Our numbers reflect the protocol, not the app.

Architecture Differences

KEIBIDROP keeps one encrypted TCP connection open and multiplexes all operations over gRPC. There is no per-file setup. Croc does a full PAKE exchange per transfer; wormhole does SPAKE2 through a mailbox server per transfer.

The StreamFile RPC pushes all chunks server-to-client with zero per-chunk round-trips. Croc and scp use request-response patterns.

Data goes directly between peers. Croc routes through a relay process, adding an extra hop and memory copy even on localhost.

KEIBIDROP uses ChaCha20-Poly1305. On machines without AES-NI (ARM Macs, Linux ARM servers), ChaCha20 is faster than AES. On x86 with AES-NI, AES-GCM is 13% faster. We chose ChaCha20 for consistent cross-platform performance. Switching to AES-GCM would close the gap with LocalSend's protocol on x86 hardware.

Encryption Overhead

LayerThroughputOverhead
Plain gRPC (no encryption)657 MB/sbaseline
Encrypted gRPC (ChaCha20-Poly1305)442 MB/s1.49x (33%)
Encrypted FUSE E2E233 MB/s2.82x (48% FUSE + 33% encryption)

33% overhead for end-to-end encryption with ChaCha20-Poly1305. Every byte is authenticated and encrypted. Tools that terminate TLS at a relay (like WeTransfer) avoid this cost because the relay decrypts and re-encrypts, but the relay can then read the data.

Summary

KEIBIDROP at 442 MB/s (gRPC) is 2.9x faster than croc and 3.5x faster than wormhole. The difference comes from architecture: persistent connection, no relay hop, push-based streaming.

LocalSend's protocol at 612 MB/s is 28% faster with the same cipher. The gap is gRPC framing and chunk tracking. Switching to AES-GCM on x86 would narrow it to ~15%.

scp is faster on localhost because the page cache eliminates disk I/O. On real networks this advantage disappears.

The FUSE path at 233 MB/s adds 48% overhead from kernel-userspace context switches. This is the cost of mounting a virtual filesystem where you can run git, open files in editors, and browse shared directories.

The encrypted gRPC path (442 MB/s) is the speed for pure file transfer. Through FUSE, 233 MB/s.

Benchmark script and raw data: KD-Benchmarks

10 min read | KEIBIDROP Series | Optimizing Transfer | Technical Deep Dive | Feature Comparison