KEIBIDROP Footprint

What the daemon and the desktop app cost in memory and on disk

5 min read | KEIBIDROP Series | June 2026

What this is about. Footprint measurements of KEIBIDROP, a post-quantum encrypted peer-to-peer filesystem. The engine idles at about 13 MiB. Resident memory grows with the number of files a peer tracks, not with the volume of data it moves: about 0.68 KiB per file with no FUSE mount, and 0.84 to 2.55 KiB per file with the mount up, so a peer tracking 300,000 files holds about 214 MiB with no mount, and 249 MiB to 761 MiB with the FUSE mount up depending on garbage-collector state. Moving a 1 GiB file holds a working set of about 102 MiB (no FUSE) to 169 MiB (FUSE) that does not scale with the size of the file, because streaming reuses pooled buffers. On disk, the kd daemon is one statically linked binary of about 20 MB, and the packaged downloads run 19 MB to 35 MB per platform.

Method

Two numbers bound each memory figure. The first is live resident memory, read the way the operating system reports it: ps on Linux and macOS, Task Manager on Windows. This includes memory the garbage collector has freed inside the process but has not yet returned to the operating system, so it is an upper bound. The second forces a collection and returns free pages, runtime.GC() followed by debug.FreeOSMemory(), before each reading; this is the retained working set, a lower bound. Steady-state use sits between the two.

Resident memory includes shared libraries. The kernel page cache that backs a FUSE mount is not part of process resident memory, so it is not counted here. The per-file figures come from loading files in a sweep and fitting resident memory against file count with least squares; the fits are close, with R-squared at or above 0.93. The transfer figures are the mean and peak on the receiving peer over the window of a single 1 GiB transfer.

Idle

With no files loaded, the engine resides in about 13 MiB, near identical whether the FUSE mount is up or not. The full desktop application is the engine plus the user interface, and it idles at about 116 MiB. The user interface accounts for the difference, about 103 MiB.

BuildModeIdle RSS (MiB)
engine (kd)no-FUSE13.41
engine (kd)FUSE13.65
desktop appno-FUSE116.43
desktop appFUSE116.22

Memory per file

Resident memory grows with the number of files a peer tracks. With no FUSE the slope is about 0.68 KiB per file. With the mount up the cost is higher, because each file also carries the attributes the kernel asks for, and the measurement splits into the two bounds above: about 2.55 KiB per file live, and about 0.84 KiB per file once the collector is forced and free pages returned.

ModePer fileAt 100k filesAt 300k files
no-FUSE0.68 KiB80 MiB214 MiB
FUSE, compacted (lower bound)0.84 KiB89 MiB249 MiB
FUSE, live (upper bound)2.55 KiB263 MiB761 MiB

The gap between the two FUSE rows is garbage-collector headroom, not a leak. The live row holds pages the collector has reclaimed but not yet handed back to the operating system; the compacted row is what remains after it does. A long-running peer sits between the two rows and drifts toward the lower one when it goes quiet.

During a transfer

Moving a large file does not scale memory with the size of the file. The receiving side reuses fixed-size buffers from a pool rather than allocating per file, so the cost of a transfer is roughly constant. On a 1 GiB transfer the receiving peer held a working set of about 102 MiB with no FUSE and 169 MiB with FUSE. That set is the streaming buffers, the gRPC windows, and the data in flight, not a copy of the file. Within the transfer window the peak ran 7.7 MiB above the mean with no FUSE and 35.6 MiB above with FUSE.

ModeMean RSSPeak RSSPeak above meanThroughput
no-FUSE102 MiB110 MiB7.7 MiB399 MB/s
FUSE169 MiB205 MiB35.6 MiB432 MB/s

The buffer pool is why the working set stays flat. An earlier change to the encrypted connection replaced a per-message copy with a reused buffer and pooled the encryption scratch space, which cut heap churn on a 1 GiB transfer by about a third (commit 1012224). The figures here are downstream of that work.

Binary size

On disk, the kd daemon and command-line tool is a single statically linked binary of about 20 MB (20,445,816 bytes on the build measured). The packaged downloads are that binary plus the desktop application and its assets, wrapped for each platform, and they run from 19 MB to 35 MB. The figures below are the v0.3.5 release artifacts.

PlatformPackageDownload size
Windows x86-64.zip19.4 MB
macOS arm64.dmg32.3 MB
macOS arm64.tar.gz29.2 MB
macOS x86-64.tar.gz31.9 MB
Linux x86-64.tar.gz34.2 MB
Linux x86-64.deb34.6 MB

About 20 MB is what a self-contained Go binary costs. There is no external runtime to install and nothing to resolve at startup. The binary carries the Go runtime, garbage collector, and scheduler; the cryptographic stack (X25519 and ML-KEM for the handshake, ChaCha20-Poly1305 for the transport); the gRPC and Protocol Buffers machinery; and the FUSE bindings. The trade is a larger file in exchange for no dependency to install. For a tool people run on three operating systems, the single file is worth the size.

What the numbers say

The footprint is bounded and predictable. An idle peer costs a few tens of MiB. A peer tracking hundreds of thousands of files costs low hundreds of MiB, set by the file count rather than by how much data has passed through it, because on-demand mode keeps file contents in a sparse cache file on disk and only the file metadata in memory. A transfer adds tens of MiB regardless of file size. On disk it is one binary of about 20 MB. None of these numbers grow with the volume of data transferred, which is the property we want from a filesystem meant to sit mounted and mostly idle.

Memory figures are live resident memory (upper bound) and GC-compacted retained set (lower bound), per-file slopes fit by least squares (R-squared at or above 0.93). Transfer figures are the receiving peer over one 1 GiB transfer. Binary sizes are the v0.3.5 release artifacts and the measured kd binary.

5 min read | KEIBIDROP Series | Romania to Singapore | Optimizing Encrypted Transfer | SecureConn Performance

Andrei ran the memory and binary-size measurements.