Es el sueño () una buena idea para el bucle principal de una aplicación de trabajo de programación

StackOverflow https://stackoverflow.com/questions/1179301

Pregunta

Estoy escribiendo una aplicación de trabajo de programación en Ruby para mi trabajo (principalmente para mover archivos a través de varios protocolos a una frecuencia dada)

Mi bucle principal se ve así:

while true do
  # some code to launch the proper job
  sleep CONFIG["interval"]
end

Está funcionando a las mil maravillas, pero no estoy muy seguro si es lo suficientemente seguro como la aplicación pueda ejecutarse en un servidor con el correr de software intensivo de la CPU.

¿Hay otra manera de hacer la misma cosa, o se sleep() lo suficientemente seguro en mi caso?

¿Fue útil?

Solución

Uso del sueño es probable bien para cosas rápidas y sucias. Pero para las cosas que necesitan un poco más de robustez o fiabilidad Sugiero que el sueño es el mal :) El problema con el sueño es que el hilo es (estoy asumiendo de Windows aquí ...) es realmente el sueño - el programador no se ejecutará el hilo hasta algún tiempo después de intervalo de reposo ha pasado.

Durante este tiempo, el hilo no se despierte para nada. Esto significa que no se puede cancelar, o se despierta para procesar algún tipo de evento. Por supuesto, el proceso puede ser matado, pero eso no le da el hilo de dormir una oportunidad para despertar y limpia nada.

No estoy familiarizado con Ruby, pero supongo que tiene algún tipo de instalación para esperar en varias cosas. Si es posible, sugiero que en lugar de utilizar el sueño, que waint en dos cosas \

  1. Un temporizador que despierta el hilo periódicamente para hacer su trabajo.
  2. Un evento que se establece cuando él proceso necesita cancelar o bastante (atrapando control-C por ejemplo).

Sería aún mejor si hay algún tipo de evento que puede ser utilizado para señalar la necesidad de hacer el trabajo. Esto evitaría el sondeo con un temporizador. Esto conduce generalmente a disminuir la utilización de recursos y un sistema más sensible.

Otros consejos

Cada vez que siente la necesidad de bloquear, utilizo un bucle de eventos; por lo general libev. Aquí es un rubí unión:

http://rev.rubyforge.org/rdoc/

Básicamente, sleep está perfectamente bien si desea que su proceso de ir a dormir sin tener nada más en juego en el fondo. Si alguna vez quieres hacer otras cosas, sin embargo, como el sueño y también esperar a que las conexiones TCP o un gestor de archivo legible para convertirse, entonces vas a tener que utilizar un bucle de eventos. Así que, ¿por qué no utilizar una al principio?

El flujo de su aplicación será:

main {
   Timer->new( after => 0, every => 60 seconds, run => { <do your work> } )
   loop();
}

Cuando se quiere hacer otras cosas, que acaba de crear el observador, y sucede para usted. (Los trabajos que se están ejecutando también pueden crear los observadores.)

Si no es necesario un intervalo exacto, entonces tiene sentido para mí. Si necesita ser despertado a la misma hora y sin deriva, es probable que desee utilizar algún tipo de temporizador externo. Pero cuando estás dormido, no está utilizando recursos de la CPU. Es el cambio de tarea que es caro.

Mientras sleep(timeout) es perfectamente apropiada para algunos diseños, hay una advertencia importante a tener en cuenta.

Rubí instala manejadores de señales con SA_RESTART (ver aquí ), lo que significa que su sleep (o select(nil, nil, nil, timeout) equivalente) no pueden ser fácilmente interrumpidos. Su manejador de la señal va a disparar, pero el programa irá a la derecha de nuevo a sleep. Esto puede ser un inconveniente si se desea que reaccionen a tiempo a, digamos, un SIGTERM.

Tenga en cuenta que ...

#! /usr/bin/ruby
Signal.trap("USR1") { puts "Hey, wake up!" }
Process.fork() { sleep 2 and Process.kill("USR1", Process.ppid) }
sleep 30
puts "Zzz.  I enjoyed my nap."

... tomará unos 30 segundos para ejecutar, en lugar de 2.

Como solución alternativa, es posible que en lugar de lanzar una excepción en su manejador de la señal, lo que interrumpe el sueño (o cualquier otra cosa!) Anterior. También puede cambiar a un bucle basado en select y el uso de una variante de la truco auto-pipe a despertar "temprana" a la recepción de una señal. Como otros han señalado, las bibliotecas de eventos plenamente las funciones están disponibles, también.

Se suele utilizar la CPU mientras se está durmiendo, pero si usted está durmiendo durante mucho tiempo que estaría más preocupado de la carrera intérprete de Ruby sosteniendo memoria mientras no estaba haciendo nada. Esto no es tan grande de un acuerdo de Tho.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top