A group of researchers from German universities results , during which 10 versions of a standard driver for 10-gigabit Intel Ixgbe (X5xx) network cards were developed in different programming languages. The driver operates in user space and is implemented in C, Rust, Go, C#, Java, OCaml, Haskell, Swift, JavaScript, and Python. When writing the code, the main focus was on achieving the highest possible performance while considering the characteristics of each language. All versions are functionally identical and consist of approximately 1000 lines of code. The project's developments under the BSD license.
The Rust driver variant proved to be very close in performance to the reference driver written in C. Under load with simultaneous transmission of blocks of 32 packets, the Rust driver lagged slightly behind, but in tests with more than 32 packets per block, its speed was almost indistinguishable from the C driver, demonstrating a performance level of processing 28 million packets per second on a server with a Xeon E3-1230 v2 3.3 GHz CPU.
The next tier in performance was occupied by the drivers in Go and C#, which showed fairly close results (the Go driver excelled in tests with blocks containing up to 16 packets and began to slightly lag in tests with more than 16 packets in the block). At 256 packets per block, the peak performance of the C# driver was about 28 million packets per second, while the Go driver achieved around 25 million packets per second.
Next, with relatively close results, were the drivers in
Java, OCaml, and Haskell, which were already noticeably behind the previously discussed options and could not surpass the threshold of 12 million packets per second. Even more lagging were the drivers in Swift and JavaScript, which could process streams at the level of 5 million packets per second.
Bringing up the rear was the driver written in Python, which could process only 0.14 million packets per second. The implementation in Python was used to assess the speed of interpreter performance without JIT and without specific optimizations (the code was run using CPython 3.7 and was not compatible with PyPy, but it is noted that optimizing data storage structures could potentially increase performance by about 10 times).
Additional tests were conducted on latency, which demonstrated the effectiveness of buffering and the impact of garbage collection. The tests measured the delay after redirecting each packet by the driver compared to a precisely known sending time. Drivers in C and Rust continued to lead, with results that were almost indistinguishable for a stream of 1 million packets per second (approximately 20 µs). The driver in Go performed well, lagging slightly behind the leaders and also maintaining around 20 µs. The C# driver showed delays of about 50 µs.
The largest delays were shown by JavaScript and Java drivers (delays exceeding 300 µs).
The study was conducted to assess the feasibility of developing drivers and operating system components in higher-level languages than C. Currently, 39 out of 40 memory-related issues in Linux are attributed to drivers, making the application of a safer language and the relocation of drivers from the kernel to user space issues of ongoing relevance. Manufacturers are already actively experimenting in this direction (for example, Google developed a TCP stack for the OS in Go, CloudFlare created an implementation of the QUIC protocol in Rust, and Apple moved the TCP stack on mobile devices to user space). In the course of this work, it was concluded that Rust is the best candidate for driver development. The capabilities provided by Rust allow for the resolution of issues arising from low-level memory management, at the cost of a performance drop of about 2%-10% compared to C drivers. Go and C# are also deemed suitable for creating system components in situations where delays of milliseconds, caused by the use of garbage collection, are acceptable.
A group of researchers from German universities published the results
Source: opennet.ru
