Wie ist Node.js von Natur aus schneller, wenn es intern immer noch auf Threads basiert?


281

Ich habe gerade das folgende Video gesehen: Einführung in Node.js und verstehe immer noch nicht, wie Sie die Geschwindigkeitsvorteile erhalten.

Hauptsächlich sagt Ryan Dahl (der Ersteller von Node.js), dass Node.js auf Ereignisschleifen anstatt auf Threads basiert. Threads sind teuer und sollten nur den Experten der gleichzeitigen Programmierung überlassen werden.

Später zeigt er dann den Architekturstapel von Node.js mit einer zugrunde liegenden C-Implementierung, die intern über einen eigenen Thread-Pool verfügt. Offensichtlich würden Node.js Entwickler niemals ihre eigenen Threads starten oder den Thread-Pool direkt verwenden ... sie verwenden asynchrone Rückrufe. So viel verstehe ich.

Was ich nicht verstehe, ist der Punkt, dass Node.js immer noch Threads verwendet ... es verbirgt nur die Implementierung. Wie ist das schneller, wenn 50 Leute 50 Dateien anfordern (derzeit nicht im Speicher), dann sind nicht 50 Threads erforderlich ?

Der einzige Unterschied besteht darin, dass der Entwickler von Node.js, da es intern verwaltet wird, die Thread-Details nicht codieren muss, sondern weiterhin die Threads verwendet, um die Anforderungen für E / A-Dateien (Blockierungsdateien) zu verarbeiten.

Nehmen Sie also nicht wirklich nur ein Problem (Threading) und verstecken es, solange dieses Problem noch besteht: hauptsächlich mehrere Threads, Kontextwechsel, Deadlocks ... usw.?

Es muss einige Details geben, die ich hier immer noch nicht verstehe.


14
Ich bin geneigt, Ihnen zuzustimmen, dass die Behauptung etwas vereinfacht ist. Ich glaube, der Leistungsvorteil des Knotens besteht aus zwei Dingen: 1) Die tatsächlichen Threads sind alle auf einem relativ niedrigen Niveau enthalten und bleiben daher in Größe und Anzahl eingeschränkt, und die Thread-Synchronisation wird somit vereinfacht. 2) Das "Umschalten" auf Betriebssystemebene select()ist schneller als das Austauschen von Thread-Kontexten.
Pointy

Antworten:


140

Es gibt tatsächlich ein paar verschiedene Dinge, die hier zusammengeführt werden. Aber es beginnt mit dem Mem, dass Threads einfach sehr hart sind. Wenn sie also hart sind, ist es wahrscheinlicher, dass Sie Threads verwenden, um 1) aufgrund von Fehlern zu brechen und 2) sie nicht so effizient wie möglich zu verwenden. (2) ist derjenige, nach dem Sie fragen.

Denken Sie an eines der Beispiele, die er gibt, bei denen eine Anfrage eingeht und Sie eine Abfrage ausführen, und machen Sie dann etwas mit den Ergebnissen davon. Wenn Sie es in einer Standardprozedur schreiben, sieht der Code möglicherweise folgendermaßen aus:

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

Wenn Sie aufgrund der eingehenden Anforderung einen neuen Thread erstellt haben, in dem der obige Code ausgeführt wurde, befindet sich dort ein Thread, der während der query()Ausführung überhaupt nichts unternimmt . (Laut Ryan verwendet Apache einen einzelnen Thread, um die ursprüngliche Anforderung zu erfüllen, während Nginx ihn in den Fällen, über die er spricht, übertrifft, weil dies nicht der Fall ist.)

Wenn Sie wirklich schlau wären, würden Sie den obigen Code so ausdrücken, dass die Umgebung während der Ausführung der Abfrage etwas anderes tun könnte:

query( statement: "select smurfs from some_mushroom", callback: go_do_something_with_result() );

Dies ist im Grunde das, was node.js tut. Sie dekorieren Ihren Code im Grunde genommen so, dass die Umgebung klug darüber ist, was wann ausgeführt wird - auf eine Weise, die aufgrund der Sprache und der Umgebung, daher die Punkte bei Schließungen, praktisch ist. Auf diese Weise ist node.js nicht neu in dem Sinne, dass es asynchrone E / A erfunden hat (nicht dass irgendjemand so etwas behauptet hat), aber es ist neu darin, dass die Art und Weise, wie es ausgedrückt wird, etwas anders ist.

Hinweis: Wenn ich sage, dass die Umgebung klug sein kann, was wann ausgeführt wird, meine ich insbesondere, dass der Thread, mit dem eine E / A gestartet wurde, jetzt zur Verarbeitung einer anderen Anforderung oder einer möglichen Berechnung verwendet werden kann parallel oder starten Sie eine andere parallele E / A. (Ich bin nicht sicher, ob der Knoten hoch genug ist, um mehr Arbeit für dieselbe Anfrage zu starten, aber Sie haben die Idee.)


6
Okay, ich kann definitiv sehen, wie dies die Leistung steigern kann, da es für mich so klingt, als ob Sie Ihre CPU maximal nutzen können, weil es keine Threads oder Ausführungsstapel gibt, die nur darauf warten, dass IO zurückkehrt, damit das, was Ryan getan hat, effektiv gefunden wird eine Möglichkeit, alle Lücken zu schließen.
Ralph Caraveo

34
Ja, das einzige, was ich sagen würde, ist, dass er nicht einen Weg gefunden hat, die Lücken zu schließen: Es ist kein neues Muster. Was anders ist, ist, dass er Javascript verwendet, damit der Programmierer sein Programm auf eine Weise ausdrücken kann, die für diese Art von Asynchronität viel bequemer ist. Möglicherweise ein pingeliges Detail, aber immer noch ...
jrtipton

16
Es ist auch erwähnenswert, dass Node für viele der E / A-Aufgaben jede verfügbare asynchrone E / A-API auf Kernelebene verwendet (epoll, kqueue, / dev / poll, was auch immer)
Paul

7
Ich bin mir immer noch nicht sicher, ob ich es vollständig verstehe. Wenn wir berücksichtigen, dass innerhalb einer Webanforderung E / A-Vorgänge die meiste Zeit benötigen, um die Anforderung zu verarbeiten, und wenn für jede E / A-Operation ein neuer Thread erstellt wird, werden wir dies für 50 Anforderungen tun, die sehr schnell hintereinander eingehen Wahrscheinlich laufen 50 Threads parallel und führen ihren E / A-Teil aus. Der Unterschied zu Standard-Webservern besteht darin, dass dort die gesamte Anforderung auf dem Thread ausgeführt wird, während in node.js nur der E / A-Teil vorhanden ist. Dies ist jedoch der Teil, der die meiste Zeit in Anspruch nimmt und den Thread warten lässt.
Florin Dumitrescu

13
@ SystemParadox danke für den Hinweis. Ich habe in letzter Zeit tatsächlich einige Nachforschungen zu diesem Thema angestellt, und tatsächlich ist der Haken, dass asynchrone E / A bei ordnungsgemäßer Implementierung auf Kernelebene keine Threads verwenden, während asynchrone E / A-Operationen ausgeführt werden. Stattdessen wird der aufrufende Thread freigegeben, sobald eine E / A-Operation gestartet und ein Rückruf ausgeführt wird, wenn die E / A-Operation abgeschlossen ist und ein Thread dafür verfügbar ist. Node.js kann also 50 gleichzeitige Anforderungen mit 50 E / A-Vorgängen (fast) parallel mit nur einem Thread ausführen, wenn die asynchrone Unterstützung für die E / A-Vorgänge ordnungsgemäß implementiert ist.
Florin Dumitrescu

32

Hinweis! Dies ist eine alte Antwort. Während es in der groben Gliederung immer noch zutrifft, haben sich einige Details möglicherweise aufgrund der rasanten Entwicklung von Node in den letzten Jahren geändert.

Es werden Threads verwendet, weil:

  1. Die Option O_NONBLOCK von open () funktioniert nicht für Dateien .
  2. Es gibt Bibliotheken von Drittanbietern, die keine nicht blockierenden E / A-Vorgänge anbieten.

Um nicht blockierende E / A zu fälschen, sind Threads erforderlich: Blockieren Sie E / A in einem separaten Thread. Es ist eine hässliche Lösung und verursacht viel Aufwand.

Auf Hardware-Ebene ist es noch schlimmer:

  • Mit DMA entlädt die CPU E / A asynchron.
  • Daten werden direkt zwischen dem E / A-Gerät und dem Speicher übertragen.
  • Der Kernel verpackt dies in einen synchronen, blockierenden Systemaufruf.
  • Node.js schließt den blockierenden Systemaufruf in einen Thread ein.

Das ist einfach nur dumm und ineffizient. Aber es funktioniert zumindest! Wir können Node.js genießen, weil es die hässlichen und umständlichen Details hinter einer ereignisgesteuerten asynchronen Architektur verbirgt.

Vielleicht wird jemand in Zukunft O_NONBLOCK für Dateien implementieren? ...

Bearbeiten: Ich habe dies mit einem Freund besprochen und er sagte mir, dass eine Alternative zu Threads das Abrufen mit select ist : Geben Sie ein Timeout von 0 an und führen Sie E / A für die zurückgegebenen Dateideskriptoren durch (jetzt, da sie garantiert nicht blockieren).


Was ist mit Windows?
Pacerier

Entschuldigung, keine Ahnung. Ich weiß nur, dass libuv die plattformneutrale Schicht für asynchrone Arbeit ist. Am Anfang von Node gab es keine Libuv. Dann wurde beschlossen, libuv abzuspalten, was den plattformspezifischen Code einfacher machte. Mit anderen Worten, Windows hat seine eigene asynchrone Geschichte, die sich möglicherweise völlig von Linux unterscheidet, aber für uns spielt es keine Rolle, weil libuv die harte Arbeit für uns erledigt.
Nalply

28

Ich fürchte, ich mache hier "das Falsche", wenn ja, lösche mich und ich entschuldige mich. Insbesondere sehe ich nicht, wie ich die hübschen kleinen Anmerkungen erstelle, die einige Leute erstellt haben. Ich habe jedoch viele Bedenken / Beobachtungen zu diesem Thema.

1) Das kommentierte Element im Pseudocode in einer der populären Antworten

result = query( "select smurfs from some_mushroom" );
// twiddle fingers
go_do_something_with_result( result );

ist im Wesentlichen falsch. Wenn der Thread rechnet, dreht er nicht mit den Daumen, sondern erledigt die notwendige Arbeit. Wenn andererseits nur auf den Abschluss der E / A gewartet wird und dann keine CPU-Zeit verwendet wird, besteht der springende Punkt der Thread-Steuerungsinfrastruktur im Kernel darin, dass die CPU etwas Nützliches findet. Die einzige Möglichkeit, "Daumen zu drehen", wie hier vorgeschlagen, besteht darin, eine Abfrageschleife zu erstellen, und niemand, der einen echten Webserver codiert hat, ist dazu nicht in der Lage.

2) "Threads sind hart", macht nur im Zusammenhang mit dem Datenaustausch Sinn. Wenn Sie im Wesentlichen unabhängige Threads haben, wie dies bei der Verarbeitung unabhängiger Webanforderungen der Fall ist, ist das Threading trivial einfach. Sie codieren einfach den linearen Ablauf für die Verarbeitung eines Jobs und wissen, dass mehrere Anforderungen verarbeitet werden wird effektiv unabhängig sein. Persönlich würde ich es wagen, dass für die meisten Programmierer das Erlernen des Schließ- / Rückrufmechanismus komplexer ist als das einfache Codieren der Top-to-Bottom-Thread-Version. (Aber ja, wenn Sie zwischen den Threads kommunizieren müssen, wird das Leben sehr schnell sehr schwer, aber dann bin ich nicht davon überzeugt, dass der Schließ- / Rückrufmechanismus dies wirklich ändert. Er schränkt nur Ihre Optionen ein, da dieser Ansatz mit Threads immer noch erreichbar ist Wie auch immer, das '

3) Bisher hat niemand echte Beweise dafür vorgelegt, warum eine bestimmte Art von Kontextwechsel mehr oder weniger zeitaufwändig wäre als jede andere Art. Meine Erfahrung bei der Erstellung von Multitasking-Kerneln (im kleinen Maßstab für eingebettete Controller nichts Besonderes als ein "echtes" Betriebssystem) legt nahe, dass dies nicht der Fall wäre.

4) Alle Abbildungen, die ich bisher gesehen habe, um zu zeigen, wie viel schneller Node ist als andere Webserver, sind schrecklich fehlerhaft. Sie sind jedoch auf eine Weise fehlerhaft, die indirekt einen Vorteil veranschaulicht, den ich definitiv für Node akzeptieren würde (und es ist keineswegs unbedeutend). Der Knoten sieht nicht so aus, als müsste er optimiert werden (und erlaubt es auch nicht). Wenn Sie ein Thread-Modell haben, müssen Sie genügend Threads erstellen, um die erwartete Last zu bewältigen. Wenn Sie dies schlecht machen, erhalten Sie eine schlechte Leistung. Wenn zu wenige Threads vorhanden sind, befindet sich die CPU im Leerlauf, kann jedoch keine weiteren Anforderungen akzeptieren, erstellt zu viele Threads, und Sie verschwenden Kernelspeicher. In einer Java-Umgebung verschwenden Sie auch den Hauptspeicher des Heapspeichers . Für Java ist die Verschwendung von Heap der erste und beste Weg, um die Leistung des Systems zu verbessern. Weil eine effiziente Speicherbereinigung (derzeit könnte sich dies mit G1 ändern, aber es scheint, dass die Jury zumindest Anfang 2013 noch nicht über diesen Punkt informiert ist) davon abhängt, dass viel Ersatzhaufen vorhanden ist. Es gibt also das Problem: Optimieren Sie es mit zu wenigen Threads, Sie haben inaktive CPUs und einen schlechten Durchsatz, optimieren Sie es mit zu vielen und es bleibt auf andere Weise hängen.

5) Es gibt eine andere Art und Weise, wie ich die Logik der Behauptung akzeptiere, dass der Ansatz von Node "von Natur aus schneller ist", und das ist dies. Die meisten Thread-Modelle verwenden ein zeitlich begrenztes Kontextwechselmodell, das über dem geeigneteren (Wertbeurteilungsalarm :) und effizienteren (kein Wertbeurteilungs-) Präventivmodell liegt. Dies geschieht aus zwei Gründen: Erstens scheinen die meisten Programmierer die Prioritätsvoraussetzung nicht zu verstehen, und zweitens, wenn Sie das Threading in einer Windows-Umgebung lernen, ist das Timeslicing vorhanden, ob Sie es mögen oder nicht (dies verstärkt natürlich den ersten Punkt Insbesondere in den ersten Versionen von Java wurde bei Solaris-Implementierungen die Prioritätsvoraussetzung und bei Windows die Zeiteinteilung verwendet, da die meisten Programmierer nicht verstanden und sich darüber beschwert haben, dass "Threading in Solaris nicht funktioniert". Sie haben das Modell überall auf Zeitscheibe geändert. Unter dem Strich führt Timeslicing zu zusätzlichen (und möglicherweise unnötigen) Kontextwechseln. Jeder Kontextwechsel benötigt CPU-Zeit, und diese Zeit wird effektiv von der Arbeit entfernt, die für den eigentlichen Job ausgeführt werden kann. Die Zeit, die aufgrund von Zeitscheiben in den Kontextwechsel investiert wird, sollte jedoch nicht mehr als einen sehr kleinen Prozentsatz der Gesamtzeit betragen, es sei denn, es passiert etwas ziemlich Außergewöhnliches, und es gibt keinen Grund, warum ich davon ausgehen kann, dass dies in einem Fall der Fall ist einfacher Webserver). Ja, die überschüssigen Kontextwechsel, die mit Timeslicing verbunden sind, sind ineffizient (und diese treten in nicht auf und diese Zeit wird effektiv von der Arbeit entfernt, die an der eigentlichen Arbeit erledigt werden kann. Die Zeit, die aufgrund von Zeitscheiben in den Kontextwechsel investiert wird, sollte jedoch nicht mehr als einen sehr kleinen Prozentsatz der Gesamtzeit betragen, es sei denn, es passiert etwas ziemlich Außergewöhnliches, und es gibt keinen Grund, warum ich davon ausgehen kann, dass dies in einem Fall der Fall ist einfacher Webserver). Ja, die überschüssigen Kontextwechsel, die mit Timeslicing verbunden sind, sind ineffizient (und diese treten in nicht auf und diese Zeit wird effektiv von der Arbeit entfernt, die an der eigentlichen Arbeit erledigt werden kann. Die Zeit, die aufgrund von Zeitscheiben in den Kontextwechsel investiert wird, sollte jedoch nicht mehr als einen sehr kleinen Prozentsatz der Gesamtzeit betragen, es sei denn, es passiert etwas ziemlich Außergewöhnliches, und es gibt keinen Grund, warum ich davon ausgehen kann, dass dies in einem Fall der Fall ist einfacher Webserver). Ja, die überschüssigen Kontextwechsel, die mit Timeslicing verbunden sind, sind ineffizient (und diese treten in nicht aufKernel- Threads in der Regel übrigens), aber der Unterschied beträgt einige Prozent des Durchsatzes, nicht die Art von Ganzzahlfaktoren, die in den Leistungsansprüchen enthalten sind, die häufig für Node impliziert werden.

Wie auch immer, ich entschuldige mich dafür, dass alles lang und unruhig ist, aber ich habe wirklich das Gefühl, dass die Diskussion bisher nichts bewiesen hat, und ich würde mich freuen, von jemandem in einer dieser beiden Situationen zu hören:

a) eine echte Erklärung, warum Node besser sein sollte (über die beiden oben beschriebenen Szenarien hinaus, von denen das erste (schlechte Abstimmung) meiner Meinung nach die wahre Erklärung für alle Tests ist, die ich bisher gesehen habe ] Je mehr ich darüber nachdenke, desto mehr frage ich mich, ob der von einer großen Anzahl von Stapeln verwendete Speicher hier von Bedeutung sein könnte. Die Standardstapelgrößen für moderne Threads sind in der Regel ziemlich groß, aber der von a zugewiesene Speicher Ein geschlossenes Ereignissystem wäre nur das, was benötigt wird.

b) ein echter Benchmark, der dem Thread-Server Ihrer Wahl tatsächlich eine faire Chance bietet. Zumindest auf diese Weise müsste ich aufhören zu glauben, dass die Behauptungen im Wesentlichen falsch sind;> ([Bearbeiten] das ist wahrscheinlich eher stärker als beabsichtigt, aber ich bin der Meinung, dass die Erklärungen für Leistungsvorteile bestenfalls unvollständig sind, und die Die gezeigten Benchmarks sind nicht zumutbar.

Prost, Toby


2
Ein Problem mit Threads: Sie benötigen RAM. Ein sehr ausgelasteter Server kann bis zu einigen tausend Threads ausführen. Node.js vermeidet die Threads und ist somit effizienter. Die Effizienz besteht nicht darin, Code schneller auszuführen. Es spielt keine Rolle, ob Code in Threads oder in einer Ereignisschleife ausgeführt wird. Für die CPU ist es das gleiche. Aber wenn wir Threads entfernen, sparen wir RAM: nur einen Stapel anstelle einiger tausend Stapel. Außerdem speichern wir Kontextwechsel.
Nalply

3
Aber der Knoten beseitigt keine Threads. Sie werden weiterhin intern für die E / A-Aufgaben verwendet, was für die meisten Webanforderungen erforderlich ist.
Levi

1
Außerdem speichert der Knoten das Schließen von Rückrufen im RAM, sodass ich nicht sehen kann, wo er gewinnt.
Oleksandr Papchenko

@levi Aber nodejs verwendet nicht die Art von "ein Thread pro Anfrage". Es wird ein E / A-Threadpool verwendet, wahrscheinlich um die Komplikation bei der Verwendung asynchroner E / A-APIs zu vermeiden (und möglicherweise open()kann POSIX nicht blockierungsfrei gemacht werden?). Auf diese Weise werden alle Leistungseinbußen amortisiert, bei denen das herkömmliche fork()/ pthread_create()-on-Request-Modell Threads erstellen und zerstören müsste. Und wie in Postscript a) erwähnt, amortisiert dies auch das Problem mit dem Stapelspeicher. Sie können wahrscheinlich Tausende von Anfragen mit beispielsweise 16 E / A-Threads bearbeiten.
Binki

"Die Standardstapelgrößen für moderne Threads sind in der Regel ziemlich groß, aber der von einem abschlussbasierten Ereignissystem zugewiesene Speicher ist nur das, was benötigt wird." Ich habe den Eindruck, dass diese in derselben Reihenfolge sein sollten. Abschlüsse sind nicht billig, die Laufzeit muss den gesamten Aufrufbaum der Single-Threaded-Anwendung im Speicher behalten (sozusagen "Emulationsstapel") und kann bereinigen, wenn ein Baumblatt als zugehöriger Abschluss freigegeben wird wird "gelöst". Dies beinhaltet viele Verweise auf On-Heap-Inhalte, die nicht durch Müll gesammelt werden können und die Leistung bei der Bereinigung beeinträchtigen.
David Tonhofer

14

Was ich nicht verstehe, ist der Punkt, dass Node.js immer noch Threads verwendet.

Ryan verwendet Threads für die Teile, die blockieren (die meisten node.js verwenden nicht blockierende E / A), da einige Teile wahnsinnig schwer zu schreiben sind und nicht blockieren. Aber ich glaube, Ryan möchte, dass alles nicht blockiert. Auf Folie 63 (internes Design) sehen Sie, dass Ryan libev (Bibliothek, die asynchrone Ereignisbenachrichtigungen abstrahiert) für die nicht blockierende Ereignisschleife verwendet . Aufgrund der Ereignisschleife benötigt node.js weniger Threads, was die Kontextumschaltung, den Speicherverbrauch usw. reduziert.


11

Threads werden nur verwendet, um Funktionen zu behandeln, die keine asynchrone Funktion haben, wie z stat().

Die stat()Funktion blockiert immer, daher muss node.js einen Thread verwenden, um den eigentlichen Aufruf auszuführen, ohne den Hauptthread zu blockieren (Ereignisschleife). Möglicherweise wird niemals ein Thread aus dem Thread-Pool verwendet, wenn Sie diese Art von Funktionen nicht aufrufen müssen.


7

Ich weiß nichts über die internen Abläufe von node.js, aber ich kann sehen, wie die Verwendung einer Ereignisschleife die Behandlung von Thread-E / A übertreffen kann. Stellen Sie sich eine Disc-Anfrage vor, geben Sie mir staticFile.x und stellen Sie 100 Anfragen für diese Datei. Jede Anforderung belegt normalerweise einen Thread, der diese Datei erneut empfängt, dh 100 Threads.

Stellen Sie sich nun die erste Anforderung vor, die einen Thread erstellt, der zu einem Herausgeberobjekt wird. Alle 99 anderen Anforderungen prüfen zunächst, ob ein Herausgeberobjekt für staticFile.x vorhanden ist. Wenn ja, hören Sie es sich an, während es seine Arbeit erledigt. Andernfalls starten Sie einen neuen Thread und damit einen neues Publisher-Objekt.

Sobald der einzelne Thread fertig ist, übergibt er staticFile.x an alle 100 Listener und zerstört sich selbst, sodass bei der nächsten Anforderung ein neuer Thread und ein neues Publisher-Objekt erstellt werden.

Es sind also 100 Threads gegenüber 1 Thread im obigen Beispiel, aber auch 1 Disc-Lookup anstelle von 100 Disc-Lookups. Die Verstärkung kann durchaus phänomenal sein. Ryan ist ein kluger Kerl!

Eine andere Sichtweise ist eines seiner Beispiele zu Beginn des Films. Anstatt:

pseudo code:
result = query('select * from ...');

Wieder 100 separate Abfragen an eine Datenbank im Vergleich zu ...:

pseudo code:
query('select * from ...', function(result){
    // do stuff with result
});

Wenn eine Abfrage bereits ausgeführt wurde, sprangen andere gleichwertige Abfragen einfach auf den Zug, sodass Sie 100 Abfragen in einer einzigen Datenbankrundfahrt haben können.


3
Bei der Datenbank geht es eher darum, nicht auf die Antwort zu warten, während andere Anfragen (die die Datenbank möglicherweise verwenden oder nicht verwenden) zurückgehalten werden, sondern nach etwas zu fragen und sich dann von ihm anrufen zu lassen, wenn es zurückkommt. Ich denke nicht, dass es sie miteinander verbindet, da es ziemlich schwierig wäre, den Überblick über die Reaktion zu behalten. Ich glaube auch nicht, dass es eine MySQL-Schnittstelle gibt, mit der Sie mehrere ungepufferte Antworten auf einer Verbindung (??)
speichern können

Es ist nur ein abstraktes Beispiel, um zu erklären, wie Ereignisschleifen mehr Effizienz bieten können. Nodejs macht nichts mit DBs ohne zusätzliche Module;)
BGerrissen

1
Ja, mein Kommentar bezog sich eher auf die 100 Abfragen in einem einzigen Datenbank-Roundtrip. : p
Tor Valamo

2
Hallo BGerrissen: schöner Beitrag. Wenn also eine Abfrage ausgeführt wird, "hören" andere ähnliche Abfragen wie das obige Beispiel staticFile.X? Wenn beispielsweise 100 Benutzer dieselbe Abfrage abrufen, wird nur eine Abfrage ausgeführt, und die anderen 99 hören die erste ab. Vielen Dank !
CHAPa

1
Sie lassen es so klingen, als würde nodejs Funktionsaufrufe oder ähnliches automatisch auswendig lernen. Da Sie sich im Ereignisschleifenmodell von JavaScript nicht um die Synchronisierung des gemeinsam genutzten Speichers kümmern müssen, ist es jetzt einfacher, Dinge im Speicher sicher zwischenzuspeichern. Dies bedeutet jedoch nicht, dass nodejs dies auf magische Weise für Sie erledigt oder dass dies die Art der Leistungssteigerung ist, nach der gefragt wird.
Binki
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.