2009-02-14 7 views
6

Estoy intentando ejecutar 500 clientes que envían alguna solicitud al servidor simultáneamente para propósitos de prueba de carga. El cliente es un programa de ruby ​​nuevamente. Suena trivial. Pero estoy enfrentando un problema extraño con los hilos de rubí. Mi código se ve así:Ruby solo crea 3 subprocesos a la vez

n = 10 

n.times do 
    Thread.new do 
    `calc` 
    end 
end 

El código es una muestra. Solo intento ejecutar el comando calc desde la línea de comandos (si está intentando este código en una plataforma que no sea Windows, reemplácelo por algún comando que funcione en su línea de comando o shell). Esto luego será reemplazado por 'ruby my_client.rb' y también el valor de n se establecerá en 500 (o lo que sea).

El problema que estoy enfrentando aquí es que independientemente del número de subprocesos que quiero crear, solo se crean subprocesos a la vez. Eso es solo 3 ventanas de cálculo abiertas simultáneamente. Los hilos restantes solo esperan en una cola esperando la terminación de estos 3 hilos. Puede ser que tenga algo que ver con las llamadas de bloqueo y no bloqueo. Pero probé Java-equivalente del mismo programa y funcionó perfectamente. Es un viejo refrán que los hilos en rubí no son recomendables. ¿Es cierto que esto es un problema con los hilos de Ruby o estoy haciendo algo mal?

+0

Funciona para mí bien, 1.8.7.72-2 en Debian GNU/Linux. Estoy pensando que hay algo específico de Windows. – womble

+0

Eso es posible, pero el programa java funcionó perfectamente en la misma plataforma, la misma máquina. – Chirantan

+0

Funcionó bien para mí usando ruby ​​1.8.7 en Windows XP SP3. – Lolindrath

Respuesta

3

La implementación de "Matz" C de Ruby (MRI) no usa subprocesos nativos hasta 1.8.6. Creo que esto ha cambiado en Ruby 1.9, pero entiendo que probablemente todavía no veamos un gran rendimiento de múltiples subprocesos debido al bloqueo de Intérprete global.

Si realmente necesita un buen soporte multiproceso, y para que su software se escriba en Ruby, puede intentar ejecutarlo en JRuby. Una prueba rápida de cordura mostró que con su ejemplo obtendría 2 hilos del sistema operativo en MRI y 12 cuando ejecutase lo mismo bajo JRuby. Esto fue en OS X usando "MRI" 1.8.6 y JRuby 1.1.6.

Otra opción, ya que parece que está generando un hilo para bifurcar un nuevo proceso, podría ser utilizar DRb en ​​su lugar.

+0

Gracias por el puntero DRb. Jruby debería resolver el problema. No tiene ninguna experiencia en DRb, aprenderá y le dará una oportunidad también. Gracias :) – Chirantan

+0

El hecho de que Ruby solo tenga hilos verdes, no significa que solo debe ejecutar tres hilos a la vez. – womble

+0

Eso parece un motivo de todos modos – vava

0

Esto funcionó perfectamente para mí en os x con el compañero de texto.

n = 10 

threads = [] 
n.times do |i| 
    threads << Thread.new do 
    `mate test#{i}.txt` 
    end 
end 

threads.each { |t| t.join } 
+0

Has probado tu código. Mismo problema. Puede ser lo que Alex dice que es correcto. – Chirantan

4

El problema que está observando es específico para las aplicaciones GUI. Se pone mucho mejor cuando ejecuta cosas de línea de comando dentro de los trabajadores.

Con el ejemplo a continuación, puedo ejecutar 200 instancias de wget sin problemas, lo que probablemente sea suficiente para sus objetivos de prueba de carga.

n = 200 

threads = [] 
(1..n).each do |i| 
    threads << Thread.new do 
    puts `wget google.com` # forgive me google 
    sleep 10 
    puts "#{i} done" 
    end 
end 

threads.each do |t| # wait until all workers are done 
    t.join 
end 

Probablemente consigas muchos más trabajadores si cambias de wget a código de Ruby para buscar páginas web. Y aún así, debes recordar que los hilos de Ruby se escalan solo hasta ese punto. No espere que muchos miles o subprocesos paralelos funcionen bien; pruebe los subprocesos o el enfoque basado en la continuación en su lugar.

+0

I rand el código en Windows XP SP3, ruby ​​1.8.7 y funcionó bien. – Lolindrath

0

Es posible que desee generar procesos separados en su lugar. Kernel::fork no funciona en Windows, por lo que tendría que usar los viejos Kernel::system o Kernel::popen y crear scripts separados para eso o usar argumentos especiales de línea de comando.

Aunque Ruby 1.9 está casi allí y si puede encenderlo, tiene hilos de sistema operativo nativos y cosas así no estarían sucediendo.

Cuestiones relacionadas