5 inputs produce one buffer request
The buffer-size calculator converts tolerated receive stalls into memory. Its starting profile is illustrative. Supply a measured arrival rate, average datagram size, stall duration, burst factor, and per-packet kernel-accounting allowance.
The output is a requested SO_RCVBUF value, the unrounded arithmetic, estimated packet capacity, and Linux ceiling guidance. It is a planning value that must be validated on the deployed kernel.
Method
Use p for arrivals each second, t for tolerated stall seconds, b for burst multiplier, s for average UDP payload, and o for planned per-packet socket accounting.
text
base_packets = ceil(p * t)packets = base_packets * bcharged_bytes_per_packet = s + oraw_buffer_bytes = packets * charged_bytes_per_packetrequest_bytes = round_up(raw_buffer_bytes, selected_boundary)The default boundary is the next power-of-two MiB value. The displayed raw result remains visible so rounding never conceals the method.
The allowance o is not a Solana packet field. Linux accounts socket memory using internal allocations, metadata, alignment, and kernel-specific structures. The default planning allowance is 512 bytes per packet, matching the documented sizing example, but the user should replace it with measurements from the target host.
Linux commonly doubles an application's SO_RCVBUF request as internal accounting, then exposes that effective amount through getsockopt. The tool keeps requested bytes, expected readback, and the host ceiling distinct. Its formula never halves the application request.
Size a 300 millisecond receiver stall
Use 4,600 packets per second, a 1,160-byte average payload, 300 milliseconds of stall tolerance, burst multiplier 3, and 448 accounting bytes.
text
t = 300 / 1000 = 0.300 secondsbase_packets = ceil(4,600 * 0.300) = 1,380 packets packets = 1,380 * 3 = 4,140 packets charged_bytes_per_packet = 1,160 + 448 = 1,608 bytes raw_buffer_bytes = 4,140 * 1,608 = 6,657,120 bytesRounding upward to a power-of-two MiB produces an 8 MiB request, or 8,388,608 bytes. Give the Linux receive-memory ceiling at least that value. Under the common doubling convention, effective readback will often sit near 16 MiB.
The 4,140-packet result covers at least 300 milliseconds at three times the supplied rate, equivalent to 0.9 seconds at the base rate under this accounting assumption.
Payload-only and charged capacity differ
An 8 MiB buffer divided by the example's 1,160-byte payload appears to hold about 7,231 packets. Dividing by the 1,608-byte planning charge gives about 5,216 packets. Neither value is guaranteed because actual kernel charge varies with packet size, kernel, architecture, and receive path.
The calculator shows both estimates. The charged estimate is safer for planning. Live socket memory from ss and kernel counters determine whether the allowance was adequate.
The product wire ceiling permits a 1,228-byte packet. Substituting that maximum for the example mean changes payload planning slightly; burst rate and accounting allowance usually matter more.
Validate with a stall test
Configure the host ceiling, have the application request its calculated buffer, and read the effective value back. During representative traffic, pause receiving for 75, 150, 300, and 450 milliseconds.
Observe socket overflow, UDP receive-buffer errors, NIC drops, application sequence gaps, and maximum queued-packet age. Accept the smallest operational setting that covers the declared stall and burst target without hiding unacceptable latency.
A larger buffer prevents finite queue overflow by storing more old packets. It does not increase decoder throughput. If the application remains slower than the sustained input rate, every finite buffer eventually fills.
Kernel and application queues are different
SO_RCVBUF protects the time before the receive call removes datagrams from the socket. A separate application queue protects downstream workers while the receive thread continues. Adding their capacities does not create one interchangeable stall budget.
Only kernel capacity helps during receive-thread descheduling. If decode workers stall while receive continues, the application queue helps. Size and monitor both, keeping the application queue bounded so overload becomes visible instead of accumulating seconds of stale shreds.
Even when byte rate looks modest for the link, packet scheduling and bursts still matter. Buffer sizing begins with packets per second because every datagram consumes queue metadata and one receive operation or batch slot.
Limitations
The formula treats the burst multiplier as constant over the selected interval. Real traffic has a distribution. Measure maximum and high-percentile packet counts in short windows and replace the assumption.
The per-packet allowance is a planning estimate, not a portable kernel constant. Container limits, namespaces, sysctl ceilings, memory pressure, driver behavior, and socket options can change effective capacity.
The calculator does not size NIC rings, NAPI budgets, application channels, capture buffers, or storage. It does not repair upstream loss. A clean socket overflow counter cannot prove that all sent packets reached the NIC.
The output is memory capacity, not a latency recommendation. A strategy with a 20 millisecond usefulness window should not process a one-second backlog merely because the buffer retained it. Pair buffer capacity with a maximum packet-age policy.
How it works out the answer
Compute base_packets = ceil(packets_per_second × stall_seconds). Compute bytes = base_packets × burst_multiplier × (mean_payload_bytes + per_packet_accounting_allowance). Round bytes up to the selected allocation boundary for the SO_RCVBUF request. On Linux, compare the request with net.core.rmem_max and explain that getsockopt commonly reports twice the requested value.
Questions
- Why does the calculator add bytes to every packet?
- Kernel receive memory exceeds the datagram's UDP payload. Socket structures, metadata, alignment, and allocator behavior add a host-specific charge. A 512-byte default provides one planning estimate. Validate it with live socket memory and drop counters on the deployed kernel.
- Why can SO_RCVBUF read back larger on Linux?
- Linux often adds an equal internal accounting allocation to requested socket memory and exposes the effective total through getsockopt. The tool displays request and expected readback separately. Kernels and platforms differ, so record the returned value and validate capacity with a controlled stall test.
- Can a larger receive buffer fix a slow decoder?
- No. A larger buffer absorbs finite bursts or receive-thread stalls. If sustained processing remains below the incoming packet rate, every finite queue eventually fills. It can also preserve stale packets beyond a strategy's useful window. Monitor throughput and oldest-packet age alongside drops.