2008-12-11 13 views
5

He creado un programa cliente-servidor con Perl usando IO :: Socket :: INET. Accedo al servidor a través del sitio basado en CGI. Mi programa de servidor se ejecutará como daemon y aceptará múltiples conexiones simultáneas. El proceso de mi servidor consume aproximadamente 100 MB de espacio en la memoria (9 matrices grandes, muchas matrices ...). Quiero que estos hashes residan en la memoria y los comparta para que no tenga que crearlos para cada conexión. La creación del hash lleva entre 10 y 15 segundos.¿Cómo puedo manejar múltiples sockets dentro de un daemon Perl con gran uso de memoria?

Cada vez que se acepta una nueva conexión a través de sockets, doblo un nuevo proceso para encargarme del procesamiento de cada conexión recibida. Como el proceso principal es enorme, cada vez que doblo, el procesador intenta asignar memoria a un nuevo hijo, pero debido a la memoria limitada, lleva mucho tiempo generar un nuevo hijo, lo que aumenta el tiempo de respuesta. Muchas veces se cuelga incluso para una sola conexión.

El proceso principal crea 9 valores hash grandes. Para cada niño, necesito referirme a uno o más hashes en modo de solo lectura. No actualizaré los hash a través del niño. Quiero usar algo como copy-on-write, mediante el cual puedo compartir 100mb enteros o variables globales completas creadas por parent con todo niño? o cualquier otro mecanismo como hilos. Espero que el servidor obtenga un mínimo de 100 solicitudes por segundo y que pueda procesarlas todas en paralelo. En promedio, un niño saldrá en 2 segundos.

Estoy usando Cygwin en Windows XP con solo 1 GB de RAM. No encuentro ninguna forma de superar este problema. ¿Puedes sugerir algo? ¿Cómo puedo compartir variables y también crear 100 procesos hijo por segundo y administrarlos y sincronizarlos?

Gracias.

Respuesta

3

En lugar de horquillar, existen otros dos métodos para manejar conexiones simultáneas. O usas hilos o un método de votación.

En el enfoque de subprocesos para cada conexión se crea un nuevo subproceso que maneja las E/S de un socket. Un hilo se ejecuta en la misma memoria virtual del proceso de creación y puede acceder a todos sus datos. Asegúrese de utilizar correctamente los bloqueos para sincronizar el acceso de escritura en sus datos.

Un enfoque aún más eficiente es utilizar sondeo a través de select(). En este caso, un solo proceso/subproceso maneja todos los sockets. Esto funciona bajo el supuesto de que la mayor parte del trabajo será de E/S y que el tiempo que se pasa esperando que se terminen las solicitudes de E/S se gasta en otros sockets.

Investigue más sobre esas dos opciones y decida cuál le conviene más.

Véase, por ejemplo: http://www.perlfect.com/articles/select.shtml

2

Si tiene que muchos datos, que se preguntan por qué usted no sólo tiene que utilizar una base de datos?

2

Esta arquitectura no es apta para Cygwin. La bifurcación en sistemas Unix reales es barata, pero en sistemas Unix falsos como Cygwin es terriblemente costoso, porque todos los datos tienen que ser copiados (los equipos reales usan copia por escritura). El uso de subprocesos cambia el patrón de uso de la memoria (mayor uso de la base, pero menor aumento por subproceso), pero las probabilidades siguen siendo ineficientes.

Le aconsejaría que utilice un enfoque de proceso único utilizando sondeo, y tal vez IO no bloqueante también.

+0

¿No es la versión emulada de Windows de la horquilla de Perl un hilo en el mismo proceso? Esto me mordió recientemente y eso es lo que recuerdo haber leído. –

+0

Sí, ambos se implementan como subprocesos de Win32, pero un proceso falso no se implementa de la misma manera que un hexadecimal desde la perspectiva de Perl. –

Cuestiones relacionadas