Antwort

17

Ein Threaded-Modell erstellt für jede Anforderung einen neuen Thread. Dies bedeutet, dass Sie in Bezug auf Berechnung und Speicher einen erheblichen Mehraufwand haben. Eine Ereignisschleife wird in einem einzelnen Thread ausgeführt, was bedeutet, dass Sie den Overhead nicht erhalten.

Das Ergebnis ist, dass Sie Ihr Programmiermodell ändern müssen. Weil all diese verschiedenen Dinge im selben Thread passieren, kannst du nicht blockieren. Das bedeutet, dass Sie nicht darauf warten können, dass etwas passiert, denn das würde den gesamten Thread blockieren. Stattdessen definieren Sie einen Rückruf, der nach Abschluss der Aktion aufgerufen wird. Dies wird normalerweise als nicht blockierende E/A bezeichnet.

Pseudo Beispiel zum Blockieren I/O:

row = db_query('SELECT * FROM some_table'); 
print(row); 

Pseudo Beispiel für nicht-blockierende I/O:

db_query('SELECT * FROM some_table', function (row) { 
    print(row); 
}); 

In diesem Beispiel wird lambda (anonyme Funktionen), wie sie in JavaScript verwendet werden, die ganze Zeit. JS verwendet Ereignisse intensiv, und genau darum geht es bei Callbacks. Sobald die Aktion abgeschlossen ist, wird ein Ereignis ausgelöst, das den Rückruf auslöst. Deshalb wird es oft als Modell oder asynchrones Modell bezeichnet.

Die Implementierung dieses Modells verwendet eine Schleife, die diese Ereignisse verarbeitet und auslöst. Deshalb wird es als Ereigniswarteschlange oder Ereignisschleife bezeichnet.

Prominente Beispiele für Ereigniswarteschlange Gerüste umfassen:

+2

Ich denke, es ist wichtig zu skizzieren, dass eine Ereigniswarteschlange nicht das Fehlen von Thread-Pools bedeutet. Zum Beispiel verwendet node.js stark Thread-Pools zum internen Blockieren von Operationen. Was das Ereigniswarteschlangenmodell verändert, ist die Art und Weise, wie mit solchen Long-Taking-Aktionen zu interagieren ist. –

6

Betrachten Sie eingehende Anfragen oder Rückrufe als Ereignisse, die in die Warteschlange eingereiht und verarbeitet werden.

Das ist genau das, was in den meisten GUI-Systemen getan wird. Das System kann nicht wissen, wann ein Benutzer auf eine Schaltfläche klickt oder eine Interaktion durchführt. Wenn dies der Fall ist, wird das Ereignis an die Ereignisschleife weitergegeben, bei der es sich im Grunde um eine Schleife handelt, die nach neuen Ereignissen in der Warteschlange sucht und sie verarbeitet.

Der Vorteil ist, dass Sie nicht auf Ergebnisse warten müssen. Stattdessen registrieren Sie Rückruffunktionen, die ausgeführt werden, wenn das Ereignis ausgelöst wird. Dies ermöglicht es dem Framework, E/A-Vorgänge zu handhaben, und Sie können sich auf seine interne Effizienz verlassen, wenn Sie mit langwierigen Aktionen arbeiten, anstatt Prozesse selbst zu blockieren.

Kurz gesagt, alles läuft parallel, aber Ihr Code. Es werden nie zwei Fragmente von Callback-Funktionen gleichzeitig ausgeführt - die Event-Schleife ist ein einzelner Thread. Die Prozesse, die Prozesse extern ausführen und schließlich Ereignisse weiterleiten, können jedoch in mehreren Threads/Prozessen verteilt sein.

+0

"Die Prozesse, die Stuff extern ausführen und Ereignisse schließlich weiterleiten, können jedoch in mehreren Threads/Prozessen verteilt werden." Gilt das auch für die Vanilla-JS-Engine (d. H. Nicht Node)? Da ich selbst über dasselbe nachgedacht habe, MÜSSEN die Ereignisweiterleitung und externe Anforderungen von separaten Threads behandelt werden, selbst wenn der Thread, der den eigentlichen JS-Code ausführt, nur einer ist. Aber alles, was ich lese, sagt sogar die JS ** Engine ** ist single-threaded was mir unglaublich scheint. – The111

0

Eine evented Schleife ermöglicht Sie müssen mit der Zeit umgehen, die Sie benötigen, um mit der Festplatte oder dem Netzwerk zu kommunizieren. Nehmen Sie diese Liste der Zeit:

Source | CPU Cycles 
L1  | 3 Cycles 
L2  | 14 Cycles 
RAM | 250 Cycles 
Disk | 41,000,000 Cycles 
Network| 240,000,000 Cycles 

Die Zeit, die Sie gerade laufen in PHP ist nur CPU verschwenden.

Verwandte Themen