Frage

Ich bin ein Job-Scheduling-app in Ruby für meine Arbeit zu schreiben (vor allem Dateien mit verschiedenen Protokollen bei einer bestimmten Frequenz zu bewegen)

Meine Hauptschleife sieht wie folgt aus:

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

Es funktioniert wie ein Zauber, aber ich bin nicht wirklich sicher, ob es sicher genug, wie die Anwendung ist möglicherweise auf einem Server mit rechenintensiven Software läuft ausgeführt werden.

Gibt es einen anderen Weg, um die gleiche Sache zu tun, oder ist sicher genug in meinem Fall sleep()?

War es hilfreich?

Lösung

Schlaf zu verwenden ist wahrscheinlich OK für eine schnelle und schmutzige Dinge. Aber für Dinge, die ein bisschen mehr Robustheit und Zuverlässigkeit benötigen schlage ich vor, dass der Schlaf schlecht ist :) Das Problem mit Schlaf ist, dass das Gewinde (ich Windows hier gehe davon aus ...) ist wirklich schlafen - der Scheduler nicht den Thread ausgeführt bis einige Zeit nach dem Schlafintervall verstrichen ist.

Während dieser Zeit wird der Thread aufwecken nicht für alles auf. Das bedeutet, es kann nicht storniert werden, oder aufwachen eine Art von Ereignis zu verarbeiten. Natürlich kann der Prozess getötet werden, aber das ist nicht dem Schlaf Faden nicht aufgibt die Möglichkeit, aufzuzuwachen und sauber alles.

Ich bin nicht vertraut mit Ruby, aber ich nehme an, es irgendeine Art von Anlage verfügt über mehrere Dinge zu warten. Wenn Sie können, schlage ich vor, dass anstelle Schlaf zu verwenden, Sie waint auf zwei Dinge \

  1. Ein Timer, der den Thread wacht in regelmäßigen Abständen seine Arbeit zu tun.
  2. Ein Ereignis, das gesetzt wird, wenn er Prozess (Trapping Steuer-C zum Beispiel) zu stornieren oder ganz braucht.

Es wäre noch besser, wenn es irgendeine Art von Ereignis, das verwendet werden kann, die Notwendigkeit zu signalisieren, Arbeit zu tun. Dies würde Abfrage auf einem Timer vermeiden. Dies führt in der Regel Ressourcennutzung und ein ansprechendes System zu senken.

Andere Tipps

Jedes Mal habe ich das Bedürfnis zu blockieren, ich eine Ereignisschleife verwenden; in der Regel libev. Hier ist ein Ruby-Bindung:

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

Im Grunde ist sleep völlig in Ordnung, wenn Sie Ihren Prozess wollen schlafen gehen, ohne im Hintergrund geht auf etwas anderes zu haben. Wenn Sie jemals andere Dinge tun wollen, obwohl, wie Schlaf und auch für TCP-Verbindungen oder einen Dateihandle warten, um lesbar zu werden, dann wirst du hast eine Ereignisschleife zu verwenden. Also, warum nicht nur eine Verwendung am Anfang?

Der Ablauf Ihrer Anwendung wird sein:

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

Wenn Sie andere Dinge tun wollen, erstellen Sie einfach den Beobachter, und es geschieht für Sie. (Die Jobs, die Sie ausführen können auch Beobachter erstellen.)

Wenn Sie nicht über ein genaues Intervall benötigen, dann macht es Sinn für mich. Wenn Sie zu regelmäßigen Zeiten ohne Drift aufgeweckt werden müssen, möchten Sie wahrscheinlich eine Art von externen Timer verwenden. Aber wenn Sie schlafen, Sie verwenden keine CPU-Ressourcen. Es ist die Aufgabe Schalter, der teuer ist.

Während sleep(timeout) für einige Entwürfe perfekt geeignet ist, gibt es eine wichtige Einschränkung zu beachten.

Rubin installiert Signal-Handler mit SA_RESTART (siehe hier ), was bedeutet, dass Ihr sleep (oder gleichwertig select(nil, nil, nil, timeout)) nicht leicht unterbrochen werden kann. Ihre Signal-Handler ausgelöst werden, aber das Programm wird nach rechts zurück zu sleep gehen. Dies kann unbequem sein, wenn man wollte rechtzeitig reagieren zu können, sagen wir, ein SIGTERM.

Beachten Sie, dass ...

#! /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."

... dauert etwa 30 Sekunden auszuführen, anstatt 2.

Als Abhilfe können Sie könnten stattdessen eine Ausnahme in der Signal-Handler werfen, die den Schlaf unterbrechen würde (oder irgendetwas anderes!) Oben. Sie könnten auch zu einer select-basierten Schleife wechseln und eine Variante des Selbst Rohr Tricks zu wecken „früh“ bei Empfang eines Signals auf. Wie andere haben darauf hingewiesen, voll funktionsfähige Veranstaltung Bibliotheken verfügbar sind, auch.

Es verwendet gewohnt CPU, während er schläft, aber wenn Sie für eine lange Zeit schlafen wäre ich mehr Sorgen des Ruby-Interpreters laufenden Speicher hält, während es nichts zu tun war. Das ist nicht so große Sache tho.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top