Hola% username%
Mi tarea era comparar el rendimiento de serialización para .NET Core y Golang. Después de buscar en Internet, me encontré con un repositorio . Se considera un ejemplo simple de un microservicio REST. Esto es exactamente lo que necesito, pensé. Después de ver los resultados de la prueba, me sorprendió. Después de mirar el código fuente, me di cuenta de lo que estaba mal. Esto es lo que no me gustó:
- Para la serialización y deserialización, se selecciona una matriz de 3 elementos. Esto claramente no es suficiente.
- Para Golang, no se utilizan todas las características del lenguaje, pero, como saben, la biblioteca incorporada de codificación / json es lenta.
- Como resultado, el autor compara el rendimiento de los servidores web kestrel y net / http.
Fueron estas deficiencias las que llevaron a una consideración más detallada del rendimiento en el marco del ejemplo descrito anteriormente. Espero que les resulte interesante conocer los resultados.
Composición y descripción del software.
El código fuente del repositorio anterior también se tomó como base. Lo que se ha finalizado:
- Para la API del servidor, se usa fasthttp .
- El servidor API responde con matrices de registros.
- Cada cliente tiene varios métodos para verificar.
El código modificado está disponible en el repositorio .
Para mayor claridad, un ejemplo de respuesta JSON de la API del servidor:
[ { "Id":"id_8299119732867115081", "Name":"name_5541535679032008745", "Time":1566731141 }, ... { "Id":"id_2804604318195309547", "Name":"name_5914011395631118540", "Time":1566731142 } ]
Los clientes
Para evaluar el rendimiento en cada servicio, se implementan tres métodos:
- recibir datos de la API del servidor y enviarlos sin procesar [/ testNoProcess].
- recibir datos de la API del servidor: deserialización, serialización mediante reflexión y envío [/ testReflection]. Para .NETCore, se utilizó el paquete Newtonsoft.Json, para Golang, se utilizó la codificación / json.
- recibir datos de la API del servidor: deserialización, serialización sin usar reflexión y envío [/ testNoReflection]. Para .NETCore, se implementó una solución basada en Span para minimizar el número de asignaciones de memoria. Golang tiene una solución lista para usar: la biblioteca easyjson , que ha demostrado ser exclusivamente positiva.
Con base en estas pruebas, puede evaluar el rendimiento relativo de los servidores web (kestrel y net / http), la caída del rendimiento cuando se procesan datos utilizando la reflexión y sin ella para implementaciones en ambos idiomas.
Descripción de la metodología de prueba.
Las pruebas se llevaron a cabo en varias etapas para evaluar el rendimiento de cada idioma y cada implementación.
Para crear una carga, se seleccionó la utilidad bombardero . La utilidad se lanzó con los siguientes parámetros: -c 125 –d 120s, que se pueden interpretar de la siguiente manera: cómo usar 125 subprocesos con un tiempo de prueba de 120 segundos.
La medición del rendimiento se realizó en 3 etapas:
- Dimensión del servidor API RPS. Las mediciones se llevaron a cabo para poder evaluar la influencia de los métodos de procesamiento en el rendimiento de cada método.
- Medición de RPS del procesamiento de respuesta mediante reflexión.
- Mida el procesamiento de respuesta RPS sin usar la reflexión.
Sobre la base de estas mediciones, se obtuvieron datos sobre el rendimiento del procesamiento de la respuesta. La utilización de todos los núcleos de procesador fue del 99,8-100%. Para la evaluación, se seleccionaron los datos iniciales de 10, 30, 100 y 500 registros. Las matrices de 500 registros en producción no son comunes, pero estaba interesado en ver cómo se comporta cada uno de los idiomas.
Banco de pruebas
Todas las pruebas se ejecutaron en una máquina virtual que ejecuta Ubuntu Server 18.04 con todas las actualizaciones para agosto de 2019. Tiene las siguientes características:
- Procesador Core I7-3770K - 4 núcleos.
- RAM - 4 GB.
Para la comparación de rendimiento, se instalaron .NET Core 2.2 y Golang 1.12.
Bueno, ahora es el momento de pasar a lo más interesante: los resultados.
Resultados
A continuación se muestra una tabla con los resultados de la prueba.

Puede notar de inmediato que Golang tiene un servidor web más productivo. La diferencia es de aproximadamente el 12% en comparación con Kestrel en .NET Core.
En base a los datos anteriores, se construyeron 2 gráficos. A continuación, puede ver claramente la comparación de RPS.

Debido a la biblioteca net / http más rápida, Golang muestra buenos resultados para datos pequeños. Con un aumento en el volumen de datos, el rendimiento se compara con el cernícalo.
Cuando se utiliza la reflexión en un tamaño de datos pequeño, el RPS es aproximadamente el mismo, teniendo en cuenta el error de medición. Al aumentar el tamaño de los datos, .NET Core muestra más RPS.
Al probar sin el uso de la reflexión, ambos idiomas mostraron una ganancia de rendimiento. Golang muestra un mejor rendimiento porque inicialmente tiene un mayor RPS (solicitudes por segundo) en las pruebas sin procesamiento. En datos pequeños, la ventaja es significativa. Con el aumento en el tamaño de los datos, RPS casi se compara. En la mayor prueba de 500 registros, Golang está nuevamente por delante.

En las pruebas que utilizan la reflexión, Golang perdió en todos los frentes. La caída del rendimiento en los peores escenarios fue superior al 60%. Implementar la serialización fuera de la caja para el rendimiento generalmente no tiene valor.
Sin reflexionar, Golang fue más rápido en todas las pruebas. Y con el crecimiento de los datos, la ventaja de Golang solo está creciendo. En cualquier caso, la negativa a utilizar la reflexión proporciona un aumento significativo del rendimiento tanto para Golang como para .NETCore, que, en general, debería esperarse.
Conclusiones
¿Qué conclusiones se pueden sacar de esta pequeña comparación de rendimiento? Me gustaría formular esto en forma de pros y contras para cada una de las soluciones. Comencemos con Golang:
- Tiene un mejor rendimiento y se puede mejorar aún más, por ejemplo, mediante el uso de fasthttp como servidor web.
- Gracias a la generación de código: uso conveniente de los métodos de procesamiento sin usar la reflexión.
- Menos consumo de memoria.
.NET Core también tiene varias ventajas:
- El rendimiento es adecuado para la mayoría de los casos.
- En mi opinión, este es uno de los mejores y más convenientes entornos de desarrollo para Visual Studio.
El resultado se puede resumir de la siguiente manera: si tiene una API REST y está planeando una gran carga, lógica empresarial no demasiado complicada, es mejor usar Golang, en otros casos, puede hacerlo con .NET Core. ¿Debo reescribir soluciones preparadas de .NET Core a Golang? Todos decidirán por sí mismos.
Espero que encuentres útil este material. Todo bien