Beyond Zero-Cost: Understanding Rust Safety Overheads in Systems Code
Abstract
Rust is increasingly used as a viable alternative to C and C++ for systems development. A central appeal of Rust is its “zero-cost” abstractions and, specifically, its ability to enforce safety without the overhead of garbage collection. In practice, however, only a subset of safety properties can be enforced statically, and the runtime cost of Rust safety remains poorly understood. In this paper, we take an in-depth look at the overheads of Rust safety using the example of a fast network interface driver, one of the most performance-critical components of the modern systems stack. We develop several semantically equivalent C and Rust implementations of an Intel E810 100 GbE device driver. Our analysis shows that Rust can approach the performance of C when the code is lean, closely follows C idioms, and enforces nearly all safety properties statically. At a batch size of 64 packets, a carefully optimized safe Rust implementation achieves 93% of the throughput of unsafe C while executing approximately 12% more instructions per packet. Its only sources of runtime safety overhead are null-pointer and bounds checks. Adding overflow checking and explicit error handling to avoid panics reduces throughput by a further 7% and 10%, respectively, relative to the basic safe Rust implementation. Even seemingly simple abstractions and representation changes, such as widening a pointer representation, alter the generated machine code, increasing register pressure and introducing additional memory accesses and control instructions.