Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

307
Vistas
Medición de la latencia de los sockets de dominio Unix

Quiero comparar el rendimiento de los sockets de dominio Unix entre dos procesos con el de otro IPC.

Tengo un programa básico que crea un par de sockets y luego llama a la bifurcación. Luego, mide el RTT para enviar los 8192 bytes al otro proceso y viceversa (distintos para cada iteración).

 #include <assert.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <time.h> #include <sys/time.h> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> int main(int argc, char **argv) { int i, pid, sockpair[2]; char buf[8192]; struct timespec tp1, tp2; assert(argc == 2); // Create a socket pair using Unix domain sockets with reliable, // in-order data transmission. socketpair(AF_UNIX, SOCK_STREAM, 0, sockpair); // We then fork to create a child process and then start the benchmark. pid = fork(); if (pid == 0) { // This is the child process. for (i = 0; i < atoi(argv[1]); i++) { assert(recv(sockpair[1], buf, sizeof(buf), 0) > 0); assert(send(sockpair[1], buf, sizeof(buf), 0) > 0); } } else { // This is the parent process. for (i = 0; i < atoi(argv[1]); i++) { memset(buf, i, sizeof(buf)); buf[sizeof(buf) - 1] = '\0'; assert(clock_gettime(CLOCK_REALTIME, &tp1) == 0); assert(send(sockpair[0], buf, sizeof(buf), 0) > 0); assert(recv(sockpair[0], buf, sizeof(buf), 0) > 0); assert(clock_gettime(CLOCK_REALTIME, &tp2) == 0); printf("%lu ns\n", tp2.tv_nsec - tp1.tv_nsec); } } return 0; }

Sin embargo, noté que para cada prueba repetida, el tiempo transcurrido para la primera ejecución (i = 0) siempre es un valor atípico:

 79306 ns 18649 ns 19910 ns 19601 ns ...

Me pregunto si el kernel tiene que hacer una configuración final en la primera llamada a send() ; por ejemplo, ¿asignar 8192 bytes en el kernel para almacenar en búfer los datos entre las llamadas a send() y recv() ?

over 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Supongo que las fallas en el caché de instrucciones para el código del kernel involucrado es una gran parte de la desaceleración en la primera vez. Probablemente también falla la memoria caché de datos para las estructuras de datos del kernel que realizan un seguimiento de las cosas.

Sin embargo, la configuración perezosa es una posibilidad.

Puede probar haciendo un sleep(10) entre pruebas (incluso antes de la primera prueba). Haga algo que use todo el caché de la CPU, como actualizar una página web, entre cada prueba. Si es una configuración diferida, la primera llamada será muy lenta. De lo contrario, todas las llamadas serán igualmente lentas cuando los cachés estén fríos.

over 4 years ago · Santiago Trujillo Denunciar

0

En el kernel de Linux, puede encontrar la función ___sys_sendmsg que utiliza send . Marque aquí para ver el código.

La función tiene que copiar el mensaje del usuario (en su caso, el buf de 8 KB) del espacio del usuario al espacio del núcleo. Después de eso, recv puede volver a copiar el mensaje recibido desde el espacio del núcleo al espacio de usuario del proceso secundario.

Eso significa que necesita tener 2 memcpy y un kmalloc para un par send() recv() .

El primero es tan especial porque no se asigna el espacio donde almacenar el mensaje del usuario . Esto significa también que no está presente en la memoria caché de datos . por lo que el primer par send() - recv() asignará la memoria del kernel donde almacenar buf y eso también se almacenará en caché. Las siguientes llamadas solo usarán esa memoria usando el argumento used_address en el prototipo de la función.

Entonces tu suposición es correcta. La primera ejecución asigna los 8 KB en el kernel y usa cachés en frío, mientras que las otras solo usan datos previamente asignados y almacenados en caché.

over 4 years ago · Santiago Trujillo Denunciar

0

No es la copia de datos la que toma 80 microsegundos adicionales, eso sería extremadamente lento (solo 100 MB/s), es el hecho de que está usando dos procesos y que cuando el padre envía los datos por primera vez, estos datos necesitan esperar a que el niño termine de bifurcar y empezar a ejecutar.

Si absolutamente desea utilizar dos procesos, primero debe realizar un envío en la otra dirección para que el padre pueda esperar a que el hijo esté listo antes de comenzar a enviar.

Ej: Niño:

 send(); recv(); send();

Padre:

 recv(); gettime(); send(); recv(); gettime();

También debe darse cuenta de que su prueba depende mucho de la ubicación del proceso en los distintos núcleos de la CPU y, si se ejecuta en el mismo núcleo, provocará un cambio de tarea.

Por este motivo, le recomiendo encarecidamente que realice la medición mediante un único proceso. Incluso sin encuesta ni nada, puede hacerlo de esta manera siempre que mantenga bloques razonablemente pequeños que encajen en los búferes de socket:

 gettime(); send(); recv(); gettime();

Primero debe realizar un viaje de ida y vuelta no medido para asegurarse de que se asignan los búferes. Estoy bastante seguro de que obtendrá tiempos mucho más pequeños aquí.

over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda