Группа исследователей из немецких университетов опубликовала результаты эксперимента, в ходе которого на разных языках программирования было разработано 10 вариантов типового драйвера для 10-гигабитных сетевых карт Intel Ixgbe (X5xx). Драйвер работает в пространстве пользователя и реализован на языках C, Rust, Go, C#, Java, OCaml, Haskell, Swift, JavaScript и Python. При написании кода основное внимание уделялось достижению максимально возможной производительности с учётом особенностей каждого языка. По функциональности все варианты идентичны и состоят примерно из 1000 строк кода. Наработки проекта распространяются под лицензией BSD.
Вариант драйвера на языке Rust оказался очень близок по производительности к эталонному драйверу на языке Си. При нагрузке с единовременной отправкой блоков по 32 пакета Rust-драйвер немного отставал, но в тестах с более чем 32 пакетами в блоке по скорости практически не отличался от драйвера на Си и демонстрировал производительность на уровне обработки 28 млн пакетов в секунду на сервере с CPU Xeon E3-1230 v2 3.3 GHz.
Следующую нишу по производительности заняли драйверы на языках Go и С#, которые показали достаточно близкие результаты (драйвер на Go выигрывал в тестах с блоками, включающими до 16 пакетов, и стал немного проигрывать в тестах с более чем 16 пакетами в блоке). При 256 пакетах в блоке пиковая производительность при драйвера на C# составила примерно 28 млн пакетов в секунду, а драйвера на Go примерно 25 млн пакетов в секунду.
Далее с достаточно близкими результатами следовали драйверы на
Java, OCaml и Haskell, которые уже заметно отставали от ранее рассмотренных вариантов и не смогли преодолеть планку в 12 млн пакетов в секунду. Ещё большее отставание показали драйверы на Swift и JavaScript, которые смогли обработать потоки на уровне 5 млн пакетов в секунду.
Замкнул рейтинг драйвер на языке Python, который смог обработать всего 0.14 млн пакетов в секунду. Реализация на Python была использована для оценки скорости работы интерпретаторов без JIT и без специфичных оптимизаций (код выполнялся с использованием CPython 3.7 и не был совместим с PyPy, но отмечается, что оптимизация структур хранения данных могла бы повысить производительность примерно в 10 раз).
Дополнительно были проведены тесты на время задержки, которые показывали эффективность буферизации и влияние сборщика мусора. При тестировании измерялась задержка после перенаправления каждого пакета драйвером по сравнению с точно известным временем отправки. Лидерами по-прежнему стали драйверы на Си и Rust, результаты которых были практически неотличимы для потока в 1 млн пакетов в секунду (примерно 20 µs). Хорошо проявил себя драйвер на языке Go, который лишь немного отстал от лидеров и также держался на уровне 20 µs. Драйвер на C# показал задержки примерно в 50 µs.
Самые большие задержки показали драйверы на JavaScript и Java (задержки более 300 µs).
Исследование проведено с целью оценки возможности разработки драйверов и компонентов операционной системы на языках более высокого уровня, чем Си. В настоящее время 39 из 40 проблем при работе с памятью в Linux приходятся на драйверы, поэтому вопросы применения более безопасного языка и выноса драйверов из ядра в пространство пользователя остаются актуальными и производители уже активно экспериментируют в этом направлении (например, Google разработал TCP-стек для ОС Fuchsia на языке Go, компания CloudFlare создала реализацию протокола QUIC на языке Rust, компания Apple перенесла TCP-стек на мобильных устройствах в пространство пользователя).
В ходе проведённой работы сделан вывод, что язык Rust является лучшим кандидатом для разработки драйверов. Предоставляемые в Rust возможности позволяют избавиться от проблем, возникающих из-за низкоуровневой работы с памятью, ценой снижения производительности примерно на 2%-10% по сравнению с драйверами на языке Си. Языки Go и C# также признаны пригодными для создания системных компонентов, в ситуациях когда приемлемы задержки на уровне долей миллисекунд, вызванные применением сборщика мусора.