El Martes, 26 de Agosto de 2008 01:16, Leandro Lucarella escribió:
> Herr Groucho, el 25 de agosto a las 11:35 me escribiste:
> > Hola.
> > Para resolver un problema, se me ha planteado la necesidad de
> > hacer un programa que acepte conexiones TCP desde equipos
> > embebidos y les lea datos que dichos equipos están recabando en
> > campo.
> >
> > Actualmente el programa de esos equipos embebidos establece la
> > conexión TCP y la mantiene conectada todo el tiempo. Entonces el
> > servidor que acepta esas conexiones va a tener un socket
> > conectado con cada equipo todo el tiempo. Si hay 10 equipos,
> > tendrá 10 conexiones abiertas. Pero qué pasa cuando hay 10000
> > equipos y por lo tanto 10000 conexiones?
>
> Nada, no debería pasar nada.
>
> > El programa que va a aceptar las conexiones actualmente lanza un
> > proceso hijo por cada conexión que acepta. Eso tiene la ventaja
> > de que el tratamiento de TCP/IP y la implementación del protocolo
> > de aplicación se simplifica (sólo hay un socket del cual
> > preocuparse y si el protocolo de aplicación tiene que esperar un
> > evento, directamente se puede bloquear en un read() o write() o
> > irse a dormir con timeout en un select()). Con 10000 conexiones,
> > tendría 10001 procesos. Es esta una estrategia cuerda para
> > manejar 10000 conexiones?
>
> No. Para qué querés tener 10001 procesos si con uno alcanza y
> sobre.

Porque no quiero tener un arreglo de 10000 file descriptors, no sé si 
select() o poll() pueden monitorear tal cantidad de file descriptors 
(creo que no), y porque estaba bueno escribir el código del protocolo 
de comunicación en forma secuencial (te mando esto, me duerno hasta 
que contestes. Me fijo que contestaste, te respondo tal cosa y me 
duermo de nuevo, etc.) en lugar de por eventos y estados (en el 
socket 2182 ya mandé la preguta, en el 5748 todavía no. Ok, la mando 
y me acuerdo de que ya la mandé. Vino un paquete. En qué socket? El 
9023. Ah, en ese ya había mandado la pregunta, e iba por el segundo 
intento. Ahora funcionó? Sí, bien. Va la siguiente pregunta y vuelvo 
a 0 la cuenta de reintentos y me acuerdo que voy por la segunda 
pregunta, etc.).


> > - El sistema operativo soportará 10000 procesos (hace unos años
> > el tamaño de la tabla de procesos era elegido en tiempo de
> > compilación del kernel, en valores miserables como 200)?
>
> No los necesitás.

Vos me estás planteando que tenga 10000 instancias independientes del 
protocolo de aplicación (o bueno, las que yo quiera, no necesito 
hablar a la vez por todos los sockets) y atienda todo en un programa 
de un solo thread, o en un programa con un thread independiente para 
cada instancia del protocolo de comunicación?


> > - El stack TCP/IP soportará 10000 conexiones?
> Sí
>
> > - Qué le pasará al consumo de memoria?
> Bah... no debería ser muy alto.

En qué caso? Cada proceso hijo recibiría un stack propio... y el 
consumo de memoria se iría a la mierda.


> > - Qué le pasará al multitasking si el scheduler tiene que mirar
> > una tabla de procesos tan grande cada unas pocas decenas de
> > milisegundos?
>
> No debería pasar nada grave con un scheduler O(1) como el de Linux,
> pero los context switches probablemente sí consuman mucho más
> procesador del que quisieras.

Cómo que O(1)? Es constante el tiempo? Qué mierda hace para que sea 
constante el tiempo?


> > Qué otras estrategias son concebibles?
> 1 solo proceso, un solo thread + epoll[1] (o más simple,
> libevent[2] o libev[3]).

Bibliotecas de alto nivel que no conocía. Bien!


> > - Un único proceso que atienda y maneje todas las conexiones,
> > usando arreglos para guardar los file descriptors de los sockets,
> > select() para esperar que pase algo interesante en alguno de
> > ellos e iteraciones por todos lados?
> Es la versión ineficiente de lo que propongo =)

Ja!



> > - Un proceso que lance hijos, cada uno de los cuales maneje unos
> > pocos threads (un híbrido entre los 2)
>
> No creo que tener threads te beneficie en algo, a menos que tengas
> más de un core, por supuesto.

Me beneficia en el razopnamiento del problema. Cada comunicación es 
independiente y secuencial. Es mentalmente mucho más simple de 
modelar la situación con threads que con eventos. Ver más arriba cómo 
luce la implementación del protocolo con threads/procesos 
independientes y con eventos.


> > Sugerencias?
> Usá, libev. En la página hay benchmarks[4] (contra la libevent,
> para benchmarks de select/poll vs epoll mirá la página de libevent)
> que llegan a los 100.000 fds abiertos con tiempos razonables.
>
> Para que veas que es totalmente viable esta opción, te adjunto una
> implementación pedorra en Python hecha en 15 minutos. Solo tené en
> cuenta que tenés que levantar la cantidad máxima de fds abiertos
> que podés tener (ulimit -n) porque por default viene en 1024.

Ok, buen dato.


> Anda bien con los 10000 sockets, usando poll (NO epoll) y en un
> lenguaje interpretado. En mi Athlon XP 2200 (1.8GHz) está el CPU
> entre 80% y 85% y el load average entre 2 y 8 (con el X abierto con
> varias aplicaciones, incluido el puto Firefox que está usando 8%
> del CPU vaya uno a saber en qué). Les puse que mande un mensaje
> cada 10ms y completa una "ronda" de los 10000 fds en unos 2
> minutos.
>
> Como verás, lo tuyo es un no-problema...

Caramba. El C10K problem es un no-problem... Sos groso, sabelo.
Y gracias por los datos.


> [1] http://linux.die.net/man/4/epoll
> [2] http://monkey.org/~provos/libevent/
> [3] http://libev.schmorp.de/
> [4] http://libev.schmorp.de/bench.html

-- 
Herr Groucho

ID Jabber: [EMAIL PROTECTED]
Señal distintiva: LU5MJR - 144,550 MHz FM.
Clave pública GPG: hkp://pks.lugmen.org.ar
Fingerprint GPG: B7BD 0FC7 D9A2 66F3 4EFC  45EE 7DE2 3932 597B 6354

Responder a