2010-05-06 4 views
5

Je suis en train de concevoir une boucle d'événements pour les E/S socket asynchrones en utilisant epoll/devpoll/kqueue/poll/select (y compris windows-select).Conception et problèmes de la boucle d'événements asynchrones

J'ai deux options d'exécution, opération IO:

mode non bloquant, sondage sur EAGAIN

  1. Set socket en mode non-bloquant.
  2. Lecture/écriture sur le socket.
  3. Si l'opération aboutit, envoyez une notification d'achèvement à la boucle d'événements.
  4. Si j'obtiens EAGAIN, ajoutez le socket à "select list" et à socket de sondage.

mode de scrutin: sondage et puis exécutez

  1. socket Ajouter pour sélectionner la liste et il sondage.
  2. Attendez la notification qu'il soit lisible inscriptible
  3. lecture/écriture
  4. après notification d'achèvement à boucle d'événements de sucseeds

Pour moi, il ressemble d'abord, il faudrait système moins d'appels lors de l'utilisation en mode normal , en particulier pour l'écriture sur socket (les tampons sont assez gros). En outre, il semble qu'il serait possible de réduire le surcoût sur le nombre de "select" exécutions, en particulier il est agréable quand vous n'avez pas quelque chose qui évolue bien comme epoll/devpoll/kqueue.

Questions:

  • Y at-il des avantages de la seconde approche?
  • Y at-il des problèmes de portabilité avec des opérations non bloquantes sur les sockets/descripteurs de fichiers sur de nombreux systèmes d'exploitation: Linux, FreeBSD, Solaris, MacOSX, Windows.

Notes: S'il vous plaît ne suggèrent pas l'utilisation de boucle d'événements existant/implémentations socket-api

Répondre

3

Je ne suis pas sûr qu'il ya un problème multi-plateforme; tout au plus, vous devrez utiliser l'API Windows Sockets, mais avec les mêmes résultats. Dans le cas contraire, vous semblez interroger dans les deux cas (en évitant les temps de blocage), donc les deux approches sont correctes. Tant que vous ne vous mettez pas en position de bloquer (par exemple, quand il n'y a pas de données, écrivez quand le tampon est plein), cela ne fait aucune différence. Peut-être que la première approche est plus facile à coder/comprendre; alors, vas-y avec ça.

Il pourrait vous intéresser de consulter la documentation de libev et la c10k problem pour des idées/approches intéressantes sur ce sujet.

2

La première conception est le Proactor Pattern, le second est le Reactor Pattern

Un avantage du modèle de réacteur est que vous pouvez concevoir votre API telle que vous ne disposez pas d'allouer des tampons de lecture jusqu'à ce que les données sont réellement là être lu. Cela réduit l'utilisation de la mémoire pendant que vous attendez des E/S.

+0

Je ne vois aucune raison pour laquelle vous ne pouvez pas attendre pour allouer de la mémoire un jusqu'à besoin d'utiliser la première approche. Est-ce que je manque quelque chose? – Ioan

+2

Je suppose que oui, mais en pratique, il n'est pas implémenté de cette façon. Dans le premier cas, vous avez besoin de la mémoire tampon disponible à partir des étapes 2 à 4, dans le second, vous en avez besoin uniquement à l'étape 3. – karunski

1

de mon expérience avec les applications de socket à faible latence:

pour les écritures - essayer d'écrire directement dans la prise de fil d'écriture (vous devez obtenir boucle d'événements mutex pour cela), si écrire est incomplète abonnez-vous à écrire préparation pour les lectures - être toujours "abonné" pour la disponibilité de lecture pour toutes les sockets, de sorte que vous lisiez toujours depuis le fil de la boucle d'événement lorsque le socket est en écriture. lisible

Questions connexes