Сравнение производительности сетевого драйвера в вариантах на 10 языках программирования

Группа исследователей из немецких университетов опубликовала результаты эксперимента, в ходе которого на разных языках программирования было разработано 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.

0_1568271418.png

Следующую нишу по производительности заняли драйверы на языках 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).

0_1568272590.png

©  OpenNet