2010-05-06 6 views
5

Estoy diseñando el ciclo de eventos para socket I/O asincrónico usando epoll/devpoll/kqueue/poll/select (incluyendo Windows-select).Diseño y problemas del ciclo de eventos asíncronos

que tienen dos opciones de realización, operación IO:

modo

no bloqueante, encuesta sobre EAGAIN

  1. llaves de vaso a modo de no bloqueo.
  2. Lectura/escritura en el zócalo.
  3. Si la operación se realiza correctamente, envíe la notificación de finalización al bucle de evento.
  4. Si obtengo EAGAIN, agregue el socket a "seleccionar lista" y encuestar.

modo de sondeo: sondeo y luego ejecutar

  1. Agregar zócalo para seleccionar lista y sondear la misma.
  2. esperar la notificación de que se puede escribir legible
  3. lectura/escritura
  4. notificación de finalización del anuncio al bucle de eventos de sucseeds

Para mí se parece a primera requeriría menos llamadas al sistema cuando se utiliza en modo normal , especialmente para escribir en el zócalo (los búferes son bastante grandes). También parece que sería posible reducir la sobrecarga en la cantidad de ejecuciones de "seleccionar" , especialmente cuando no tiene algo que se adapta bien como epoll/devpoll/kqueue.

Preguntas:

  • ¿Hay alguna ventaja del segundo enfoque?
  • ¿Hay algún problema de portabilidad con operaciones sin bloqueo en sockets/descriptores de archivos en numerosos sistemas operativos: Linux, FreeBSD, Solaris, MacOSX, Windows.

Notas: Por favor, no sugieren el uso de implementaciones evento de lazo/socket-api

Respuesta

3

No estoy seguro de que hay algún problema entre plataformas existentes; como máximo, debería usar la API de Windows Sockets, pero con los mismos resultados.

De lo contrario, parece que está sondeando en ambos casos (evitando esperas de bloqueo), por lo que ambos enfoques están bien. Siempre y cuando no te pongas en posición de bloquear (por ejemplo, leer cuando no hay datos, escribir cuando el búfer está lleno), no hace ninguna diferencia.

Tal vez el primer enfoque es más fácil de codificar/comprender; así que, ve con eso.

Puede ser de su interés que revise la documentación de libev y c10k problem para ideas/enfoques interesantes sobre este tema.

2

El primer diseño es el Proactor Pattern, el segundo es el Reactor Pattern

Una de las ventajas del patrón del reactor es que usted puede diseñar su API de tal manera que usted no tiene que asignar buffers de lectura hasta que los datos que realmente está allí ser leído. Esto reduce el uso de memoria mientras espera la E/S.

+0

No veo ninguna razón por la que no puede esperar para asignar memoria un hasta que sea necesario usando el primer enfoque. ¿Me estoy perdiendo de algo? – Ioan

+2

Supongo que sí, pero en la práctica no está implementado de esa manera. En el primer caso, necesita el búfer disponible desde los pasos 2 a 4, en el segundo solo lo necesita en el paso 3. – karunski

1

de mi experiencia con baja latencia aplicaciones de socket:

para escrituras - tratar de escribir directamente en la toma de escribir hilo (que necesita para obtener mutex bucle de eventos para eso), si la escritura es incompleta suscribirse a escribir disposición con bucle de evento (select/waitformultipleobjects) y escritura desde el bucle de evento cuando el socket se puede escribir

para lecturas: siempre estará "suscrito" para la preparación de lectura para todos los sockets, por lo que siempre lee desde el bucle de evento cuando se obtiene el socket legible

Cuestiones relacionadas