Skip to main content

RELAY_BLOCK_SIZE

Constant RELAY_BLOCK_SIZE 

Source
pub const RELAY_BLOCK_SIZE: usize = _; // 65_536usize
Expand description

The block reads are cut from once the initial 16 KiB is used up.

§Why a block rather than a buffer

BytesMut::split hands the filled bytes on without copying them, which is what keeps the relay allocation-light — but the piece handed on and the piece kept share one heap block, and quinn holds its piece until the segment carrying it has been acknowledged. So the memory a tunnel occupies is blocks × block size, while the only thing bounding it — quinn’s send_window, 10 MB per connection — counts bytes. Reserving a fresh RELAY_BUF_SIZE block per read made every read, however small, pin 16 KiB: 11.7x amplification for MTU-sized reads and 238x for 64-byte ones.

§The arithmetic

A block is abandoned only once its remaining capacity falls below RELAY_BUF_SIZE, so at least RELAY_BLOCK_SIZE - RELAY_BUF_SIZE = 48 KiB of it has been handed to the client by then. Worst-case amplification is therefore 64 / 48 = 1.33x whatever the read sizes are, against a factor that grew without bound as reads got smaller.

§What it costs at rest

The trade is paid in resting size: a tunnel that has relayed a single byte holds one whole block across every wait from then on, so an idle tunnel costs 64 KiB rather than the 16 KiB it started with. Saturated at the default limits – max_connections x max_targets_per_conn – that is 4 GiB, and at the ~20 live tunnels per connection seen in production about 1.3 MB per connection. The amplification is what produces the memory peaks worth avoiding, and 1.33x beats 2x there; docs/configuration.md says the same to operators.