Comparación del rendimiento del controlador de red en 10 lenguajes de programación

Un grupo de investigadores de universidades alemanas опубликовала resultados el experimento, durante el cual se desarrollaron 10 variantes de un controlador típico para tarjetas de red Intel Ixgbe (X10xx) de 5 gigabits en diferentes lenguajes de programación. El controlador se ejecuta en el espacio del usuario y se implementa en C, Rust, Go, C#, Java, OCaml, Haskell, Swift, JavaScript y Python. Al escribir el código, el foco estuvo en lograr el mayor rendimiento posible, teniendo en cuenta las características de cada lenguaje. En términos de funcionalidad, todas las opciones son idénticas y constan de aproximadamente 1000 líneas de código. logros del proyecto propagar bajo la licencia BSD.

La versión Rust del controlador tenía un rendimiento muy similar al del controlador C de referencia. Con una carga con un solo envío de bloques de 32 paquetes, el controlador Rust se retrasó un poco, pero en pruebas con más de 32 paquetes por bloque, prácticamente no se diferenció en velocidad del controlador C y demostró rendimiento a nivel de procesamiento. 28 millones de paquetes por segundo en un servidor con una CPU Xeon E3-1230 v2 3.3 GHz.

Comparación del rendimiento del controlador de red en 10 lenguajes de programación

El siguiente nicho en cuanto a rendimiento lo ocuparon los drivers Go y C#, que mostraron resultados bastante cercanos (el driver Go ganó en pruebas con bloques que incluían hasta 16 paquetes, y empezó a perder ligeramente en pruebas con más de 16 paquetes en un bloquear). Con 256 paquetes por bloque, el rendimiento máximo para el controlador C# fue de aproximadamente 28 Mpps y para los controladores Go, de aproximadamente 25 Mpps.

A continuación, con resultados bastante cercanos, seguidos por los impulsores de
Java, OCaml y Haskell, que ya estaban notablemente por detrás de las opciones consideradas anteriormente y no pudieron superar la barra de los 12 millones de paquetes por segundo. Los controladores basados ​​en Swift y JavaScript mostraron un retraso aún mayor, que pudieron procesar flujos a un nivel de 5 millones de paquetes por segundo.

El controlador en el lenguaje Python cerró la clasificación, que pudo procesar solo 0.14 millones de paquetes por segundo. Se utilizó la implementación de Python para evaluar la velocidad de los intérpretes sin JIT y sin optimizaciones específicas (el código se ejecutó con CPython 3.7 y no era compatible con PyPy, pero se observa que la optimización de las estructuras de datos podría mejorar el rendimiento unas 10 veces).

Adicionalmente, se realizaron pruebas de latencia, las cuales mostraron la efectividad del buffering y el impacto del recolector de basura. La prueba midió la latencia después de que el controlador redirigió cada paquete, en comparación con un tiempo de envío conocido. Los líderes seguían siendo los controladores C y Rust, cuyos resultados eran casi indistinguibles para un flujo de 1 millón de paquetes por segundo (alrededor de 20 µs). El conductor en el idioma Go se desempeñó bien, que estaba solo un poco por detrás de los líderes y también se mantuvo en el nivel de 20 µs. El controlador de C# mostró retrasos de unos 50 µs.
Los controladores basados ​​en JavaScript y Java mostraron los mayores retrasos (retrasos de más de 300 µs).

Comparación del rendimiento del controlador de red en 10 lenguajes de programación

El estudio se realizó con el fin de evaluar la posibilidad de desarrollar drivers y componentes del sistema operativo en lenguajes de un nivel superior a C. Actualmente, 39 de los 40 problemas de memoria de Linux están relacionados con los controladores, por lo que los problemas de adoptar un lenguaje más seguro y sacar los controladores del kernel al espacio del usuario seguir siendo relevante y los fabricantes ya están experimentando activamente en esta dirección (por ejemplo, Google ha desarrollado una pila TCP para OS Fucsia en Go, CloudFlare creado implementación del protocolo QUIC en Rust, Apple movió la pila TCP en dispositivos móviles al espacio del usuario).

En el transcurso del trabajo realizado se concluyó que el lenguaje Rust es el mejor candidato para el desarrollo de drivers. Las funciones proporcionadas por Rust le permiten deshacerse de los problemas que surgen debido al manejo de memoria de bajo nivel, a costa de una penalización de rendimiento de aproximadamente 2%-10% en comparación con los controladores de lenguaje C. Go y C# también resultan adecuados para crear componentes del sistema en situaciones en las que la latencia de menos de un milisegundo provocada por el recolector de elementos no utilizados es aceptable.

Fuente: opennet.ru

Añadir un comentario