node.js: setInterval() überspringen Anrufe

Für ein anstehendes Projekt mit node.js ich brauche, um verschiedene housekeeping Aufgaben, die in regelmäßigen Zeiten. Speziell einige Aufgaben, die jede Millisekunde, die anderen alle 20 ms (50-mal pro Sekunde) und noch andere jeden zweiten. Also ich dachte über die Verwendung von setInterval(), mit lustigen Ergebnissen: viele Funktionsaufrufe wurden übersprungen.

Der benchmark I ist wie folgt:

var counter = 0;
var seconds = 0;
var short = 1;
setInterval(function() {
        counter ++;
    }, short);
setInterval(function() {
        seconds ++;
        log('Seconds: ' + seconds + ', counter: ' +
             counter + ', missed ' +
             (seconds * 1000 / short - counter));
    }, 1000);

Gibt es eine lange timer von einer Sekunde und eine kurze, die angepasst werden kann mit der variable short, in diesem Fall 1 ms. Jede Sekunde drucken wir die Differenz zwischen der Anzahl der erwarteten Zecken im kurzen Zyklus und die tatsächliche Anzahl der Zeiten, die der kurze counter wurde aktualisiert.

Hier ist, wie verhält es sich, wenn die kurz-timer ist 1 ms:

2012-09-14T23:03:32.780Z Seconds: 1, counter: 869, missed 131
2012-09-14T23:03:33.780Z Seconds: 2, counter: 1803, missed 197
2012-09-14T23:03:34.781Z Seconds: 3, counter: 2736, missed 264
...
2012-09-14T23:03:41.783Z Seconds: 10, counter: 9267, missed 733

Viele Funktionsaufrufe übersprungen werden. Hier ist es für 10 ms:

2012-09-14T23:01:56.363Z Seconds: 1, counter: 93, missed 7
2012-09-14T23:01:57.363Z Seconds: 2, counter: 192, missed 8
2012-09-14T23:01:58.364Z Seconds: 3, counter: 291, missed 9
...
2012-09-14T23:02:05.364Z Seconds: 10, counter: 986, missed 14

Besser, aber rund ein Funktionsaufruf wird übersprungen, jede Sekunde. Und für 20 ms:

2012-09-14T23:07:18.713Z Seconds: 1, counter: 46, missed 4
2012-09-14T23:07:19.713Z Seconds: 2, counter: 96, missed 4
2012-09-14T23:07:20.712Z Seconds: 3, counter: 146, missed 4
...
2012-09-14T23:07:27.714Z Seconds: 10, counter: 495, missed 5

Schließlich für 100 ms:

2012-09-14T23:04:25.804Z Seconds: 1, counter: 9, missed 1
2012-09-14T23:04:26.803Z Seconds: 2, counter: 19, missed 1
2012-09-14T23:04:27.804Z Seconds: 3, counter: 29, missed 1
...
2012-09-14T23:04:34.805Z Seconds: 10, counter: 99, missed 1

In diesem Fall springt Sie nur sehr wenige Anrufe (die Lücke auf 2 erhöht nach 33 Sekunden und 3 nach 108 Sekunden.

Die zahlen variieren, aber Sie sind überraschend konsistent zwischen läuft: Laufen die ersten 1 ms benchmark drei mal ergab sich eine Verzögerung nach 10 Sekunden 9267, 9259 und 9253.

Habe ich keine Referenzen für dieses spezielle problem. Es ist dies viel zitiert Ressig post und viele andere JavaScript-Fragen, aber die meisten davon ausgehen, dass der code in einem browser ausgeführt wird und nicht in node.js.

Nun für die gefürchtete Frage: was ist hier Los? Nur ein Scherz; natürlich-Funktion aufruft, werden übersprungen. Aber ich kann nicht erkennen das Muster. Ich dachte, dass die langen Zyklen können verhindern, dass die kurzen, aber es macht keinen Sinn in der 1 ms-Fall. Short cycle Funktion ruft sich nicht überlappen, da Sie einfach aktualisieren Sie eine variable, und die node.js Prozess ist in der Nähe von 5% CPU-auch bei einem kurzen Zyklus von 1 ms. Durchschnittliche Auslastung ist hoch, aber, bei etwa 0.50. Ich weiß nicht warum tausend Anrufe betonen mein system so viel, obwohl, da node.js Griffe viele weitere Kunden perfekt; es muss wahr sein, dass setInterval() ist CPU-intensiv (oder ich mache etwas falsch).

Eine naheliegende Lösung ist die group-Funktion Aufrufe mit mehr Timern, und dann kurz laufen lassen-Kreislauf-Funktion ruft viele Male, um zu simulieren eine kürzere timer. Verwenden Sie dann den langen Zyklus wie ein "Besen-Wagen", der macht keine Anrufe, verpasste in den unteren Intervallen. Ein Beispiel: bis 20 ms und 1000 ms setInterval () - Aufrufe. Für 1 ms anrufen: rufen Sie 20 mal in den 20 ms-callback. Für die 1000 ms-Anruf: überprüfen Sie, wie oft die 20ms Funktion aufgerufen wurde (z.B. 47), tun alle übrigen Anrufe (z.B. 3). Aber dieses Schema ist ein bisschen komplexer, da die Anrufe überschneiden sich auf interessante Weise; es wird auch nicht regelmäßig, obwohl es vielleicht so Aussehen mag.

Die eigentliche Frage ist: kann es besser gemacht werden, entweder mit setInterval() oder andere Zeitgeber innerhalb node.js? Vielen Dank im Voraus.

InformationsquelleAutor alexfernandez | 2012-09-14

Schreibe einen Kommentar