2009-12-01 9 views
30

Estoy construyendo un servidor Linux de muy alto rendimiento (basado en epoll, sockets no bloqueantes y disco asíncrono IO [basado en io_submit/io_getevents/eventfd]). Algunos de mis puntos de referencia muestran que la forma en que manejo los enchufes no es lo suficientemente eficiente para mis requerimientos. En particular, me preocupa obtener datos del búfer de espacio de usuario a la tarjeta de red, y de la tarjeta de red al búfer de espacio de usuario (ignoremos la llamada de archivo send por ahora).Efficient Linux sockets (DMA/copia cero)

Por lo que entiendo, la invocación de lectura/escritura en un socket Linux no bloqueante no es totalmente asíncrona: la llamada al sistema bloquea mientras copia el búfer del espacio de usuario al kernel (o al revés), y solo entonces regresa ¿Hay alguna manera de evitar esto escuchado en Linux? En particular, ¿hay una llamada de escritura totalmente asíncrona que puedo hacer en un socket que devolvería inmediatamente, DMA el búfer de espacio de usuario a la tarjeta de red, según sea necesario, y señalizar/establecer un evento/etc. ¿en la terminación? Sé que Windows tiene una interfaz para esto, pero no pude encontrar nada sobre esto en Linux.

Gracias!

Respuesta

1

AFAIK está utilizando las llamadas más eficientes disponibles si no puede usar sendfile (2). Varios aspectos del código de red de alto rendimiento eficiente están cubiertos por The C10K problem

19

Se ha hablado mucho sobre Linux-kernel recientemente acerca de proporcionar una API para algo similar, pero el problema es que no se puede DMA de buffers generales del espacio de usuario a la tarjeta de red, debido a que:

  • lo que parece de datos contiguos en el espacio de direcciones del espacio de usuario lineal es probable que no contiguos en la memoria física, que es un problema si la tarjeta de red no hace dispersión de reunir DMA;
  • En muchas máquinas, no todas las direcciones de memoria física son "DMA-able". No hay forma en este momento para que una aplicación de espacio de usuario solicite específicamente un búfer con capacidad DMA.

En los últimos núcleos, se podría tratar de usar vmsplice y splice juntos para lograr lo que quiere - vmsplice las páginas (con SPLICE_F_GIFT) que desea enviar en un tubo, y luego splice ellos (con SPLICE_F_MOVE) de la tubería en la toma.

+1

Gracias! ¿Tienes alguna corazonada de lo eficiente que sería leer/escribir? En general, ¿hay alguna guía de "mejores prácticas" en algún lugar para este tipo de cosas? Me llevó días revisar todas las API de sondeo y señalización, y luego más tiempo para compararlo todo antes de encontrar una mejor práctica para multiplexar sockets y async IO. Realmente sería útil encontrar una guía de mejores prácticas sobre tomas de corriente. Está la página del problema C10K, pero la mayor parte de la información tiene muchos años (que son las edades en el momento del kernel), y por lo general es muy poco concluyente. –

+2

'empalme' y sus amigos son bastante nuevos, así que no estoy seguro de si todavía hay algún tipo de guía de" mejores prácticas "para ellos. Deberían tener una latencia bastante baja y una copia cero siempre que sea posible; ese es el objetivo de ellos. Podría intentar preguntar en las listas de distribución de linux-net y/o linux-kernel. – caf

+2

1.5 años pasaron desde estas publicaciones, ¿algún nuevo desarrollo en esta área? @caf: ¿pudiste hacer esto con 'empalme'? –