2017-03-02 2 views
4

Gibt es eine schnellere Alternative zu window.requestAnimationFrame() für Endlosschleifen, die I/O nicht blockieren?Sehr schnelle Endlosschleife ohne blockierende E/A

Was ich in der Schleife mache, hängt nicht mit Animation zusammen, also ist es mir egal, wenn das nächste Bild bereit ist, und ich habe gelesen, dass window.requestAnimationFrame() von der Aktualisierungsrate des Monitors begrenzt wird oder zumindest bis a wartet Rahmen kann gezeichnet werden.

Ich habe versucht, die folgenden auch:

function myLoop() { 
    // stuff in loop 
    setTimeout(myLoop, 4); 
} 

(Die 4 ist da, dass der Mindestabstand in setTimeout und kleinere Werte ist noch bis 4. Standard) Allerdings habe ich eine bessere Auflösung als diese benötigen.

Gibt es etwas mit noch besserer Leistung?

Ich brauche grundsätzlich eine nicht blockierende Version von while(true).

+0

* "(Die 4 ist, weil das das minimale Intervall in setTimeout ist und kleinere Werte werden immer noch auf 4 gesetzt.)" * Es ist [komplizierter] (https://www.w3.org/TR/html5/webappapis .html # dom-windowtimers-settimeout) als das und hat sich mindestens zweimal geändert. Verwenden Sie einfach "0" und lassen Sie die Implementierung sich darum sorgen, ob sie erhöht werden soll. –

+0

@ T.J. Ich verwende Electron, also kann ich gleichzeitig auf Knotenmodule und window.blahblah zugreifen :) – Joey

+0

Wenn Sie etwas häufiger als 250 Mal pro Sekunde benötigen, warum lassen Sie es nicht einfach mehrere Iterationen gleichzeitig ausführen und dann zulassen für I/O, wiederholen? Wenn Sie eine echte Auflösung von unter vier Millisekunden haben wollen, dann denke ich, dass Sie in der falschen Sprache auf dem falschen Betriebssystem programmieren. – ASDFGerte

Antwort

4

Zwei Dinge, die früher ausgeführt wird als die setTimeout:

  • process.nextTick Rückrufe (NodeJS spezifisch):

    Die process.nextTick() Methode den Rückruf an den "nächsten Tick Warteschlange", ergänzt. Sobald der aktuelle Turn der Event-Schleife abgeschlossen ist, werden alle Callbacks aufgerufen, die sich derzeit in der nächsten Tick-Warteschlange befinden.

    Dies ist kein einfacher Alias ​​für setTimeout(fn, 0). Es ist viel effizienter. Es wird ausgeführt, bevor zusätzliche E/A-Ereignisse (einschließlich Timer) in nachfolgenden Ticks der Ereignisschleife ausgelöst werden.

  • Versprechen Siedlung Benachrichtigungen

diejenigen könnte also ein Werkzeuge für Ihre toolbelt sein, eine Mischung aus einem oder beiden der Personen mit setTimeout das Gleichgewicht zu erreichen, tun Sie wollen.

Details:

Wie Sie wahrscheinlich wissen, eine bestimmte JavaScript-Thread auf der Grundlage einer Aufgabenwarteschlange läuft (die Spezifikation nennt es eine Auftragswarteschlange); und wie Sie wahrscheinlich wissen, gibt es einen Hauptstandard-UI-Thread in Browsern und NodeJS führt einen einzelnen Thread aus.

Aber in der Tat gibt es mindestens zwei Aufgabenwarteschlangen in modernen Implementierungen: Die wichtigste wir alle denken (wo setTimeout und Event-Handler ihre Aufgaben gestellt), und die „Mikrotaskanalysierer“ Warteschlange, wo bestimmte async Operationen platziert werden während die Bearbeitung einer Hauptaufgabe (oder "Makrotask"). Diese Mikrotasks werden verarbeitet, sobald die Makrotask abgeschlossen ist, vor die nächste Makrotask in der Hauptwarteschlange   —, selbst wenn diese nächste Makrotask in die Warteschlange gestellt wurde, bevor die Mikrotasks waren.

nextTick Callbacks und Versprechen Siedlung Benachrichtigungen sind beide Mikrotasks. Bei der Planung wird also entweder ein asynchroner Rückruf geplant, der jedoch vor der nächsten Hauptaufgabe ausgeführt wird.

Wir können sehen, dass im Browser mit setInterval und ein Versprechen Auflösung Kette:

let counter = 0; 
 

 
// setInterval schedules macrotasks 
 
let timer = setInterval(() => { 
 
    $("#ticker").text(++counter); 
 
}, 100); 
 

 
// Interrupt it 
 
$("#hog").on("click", function() { 
 
    let x = 300000; 
 

 
    // Queue a single microtask at the start 
 
    Promise.resolve().then(() => console.log(Date.now(), "Begin")); 
 

 
    // `next` schedules a 300k microtasks (promise settlement 
 
    // notifications), which jump ahead of the next task in the main 
 
    // task queue; then we add one at the end to say we're done 
 
    next().then(() => console.log(Date.now(), "End")); 
 

 
    function next() { 
 
    if (--x > 0) { 
 
     if (x === 150000) { 
 
     // In the middle; queue one in the middle 
 
     Promise.resolve().then(function() { 
 
      console.log(Date.now(), "Middle"); 
 
     }); 
 
     } 
 
     return Promise.resolve().then(next); 
 
    } else { 
 
     return 0; 
 
    } 
 
    } 
 
}); 
 

 
$("#stop").on("click", function() { 
 
    clearInterval(timer); 
 
});
<div id="ticker">&nbsp;</div> 
 
<div><input id="stop" type="button" value="Stop"></div> 
 
<div><input id="hog" type="button" value="Hog"></div> 
 
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Wenn Sie das ausführen und klicken Sie auf die Hog Taste, beachten Sie, wie die Zähleranzeige friert , dann geht es weiter. Das ist wegen der 300.000 Mikrotasken, die davor geplant werden. Beachten Sie auch die Zeitstempel der drei von uns geschriebenen Protokollmeldungen (sie erscheinen nicht in der Schnipselkonsole, bis sie von einer Makrotask angezeigt werden, die Zeitstempel zeigen jedoch an, wann sie protokolliert wurden).

Also im Grunde könnten Sie eine Reihe von Mikrotasks planen, und lassen Sie diese regelmäßig auslaufen und die nächste Makrotask ausführen.


Hinweis: Ich habe setInterval für den Browser Beispiel im Snippet verwendet, aber setInterval, insbesondere kann nicht eine gute Wahl für ein ähnliches Experiment mit NodeJS sein, wie NodeJS des setInterval ist ein bisschen anders aus der in Browsern und hat einige überraschende Timing-Eigenschaften.

+0

Danke, auch wenn dies nicht die richtige Lösung für meinen Anwendungsfall war, gab ich Ihnen ein Häkchen, da es die Frage – Joey

0

gibt es einige Libs, die wie Cron-Task arbeiten können, zum Beispiel https://www.npmjs.com/package/node-cron

ich denke, dass cron verwenden, sollten einfacher und flexibler sein.

+0

Cron nicht über die zweite Auflösung hinaus beantwortet. –

Verwandte Themen