Heim > Web-Frontend > js-Tutorial > Hauptteil

Beispiel für die Implementierung der Sleep-Funktion in nodejs_node.js

WBOY
Freigeben: 2016-05-16 16:07:48
Original
3196 Leute haben es durchsucht

Das Unangenehmste an NodeJS ist seine Single-Threaded-Natur. Es kann nicht viele Dinge tun und seine Leistung ist für CPU-intensive Szenarien nicht stark genug. Ich wollte schon lange einige Lösungen im Rahmen des JavaScript-Sprachframeworks finden, um die Probleme der Unfähigkeit, Threads zu bedienen, und der schlechten Leistung zu lösen. Die Lösung, die mich am meisten beeindruckt hat, waren Fasern, aber unabhängig von Fasern oder anderen Lösungen ist die Fadenbedienung immer noch sehr umständlich und zwingt das Pferd von hinten Bedenken Sie, dass JavaScript von Natur aus nicht lösbar ist. Das Peinlichste ist, dass die Nachrichtenübermittlung zwischen Threads im JavaScript-Sprachframework häufig sehr eingeschränkt ist und Objekte nicht wirklich gemeinsam genutzt werden können.

Die Add-on-Methode von nodejs ist zweifellos hervorragend, mit extrem hoher Flexibilität, vollständigen Funktionen und der Leistung von nativem Code. Einfach ausgedrückt ermöglicht es NodeJS, das C/C-Modul direkt aufzurufen, bei dem es sich um einen gemischten Entwicklungsmodus aus Javascript und Native handelt. Das ist eine gute Sache, warum nicht nutzen? Addon sollte ein großes Thema sein. Ich möchte heute nicht zu ausführlich darüber sprechen. Implementieren Sie dann eine Schlaffunktion und betrachten Sie diese als Einstieg.

schlafen

Warum kann JavaScript keinen echten Schlaf implementieren? Die Schlafmethode registriert ein Signal beim Betriebssystemkernel und sendet nach einer bestimmten Zeit ein Wecksignal, während der Thread selbst hängt. Wenn der Thread schläft (1000), bedeutet dies im Wesentlichen, dem Betriebssystem mitzuteilen: Weisen Sie mir innerhalb von 1000 ms keine CPU-Zeit zu. Daher kann der Ruhezustand sicherstellen, dass der Thread beim Anhalten keine CPU-Ressourcen mehr beansprucht. JavaScript läuft in einem einzelnen Thread und hebt das Thread-Konzept auf. Natürlich gibt es keine Möglichkeit, den Haupt-Thread anzuhalten und zu unterbrechen.

Einige Leute werden auch versuchen, Javascript zu verwenden, um den Schlaf zu implementieren, zum Beispiel:

Code kopieren Der Code lautet wie folgt:

Funktion Sleep(sleepTime) {
for(var start = neues Datum; neues Datum - start <= sleepTime; ) { }
}

Dabei wird eine leere Schleife verwendet, um die Ausführung des Hauptprozesses zu blockieren, um den Schlaf zu implementieren, der offensichtlich weit vom echten Schlaf entfernt ist.

Was wäre, wenn wir einen echten Schlaf einführen würden?

Umgebungsvorbereitung

Entwicklungsumgebung

Einige meiner Blogs haben es schon einmal gesagt, daher werde ich es hier weglassen: node.js npm, python 2.7, visual studio/x-code.

Kompilierungstools

Das Kompilierungstool muss Node-Gyp verwenden. Wenn Node-Gyp nicht im Lieferumfang enthalten ist, führen Sie bitte Folgendes aus:

Code kopieren Der Code lautet wie folgt:
npm install -g node-gyp

Ich habe nicht die Energie, die Funktionen von GYP zu studieren. Wenn Sie mit anderen Compilern wie GCC vertraut sind, ist es nicht ausgeschlossen, dass GYP Inkompatibilitäten aufweist und auch die Kompilierungsoptionen und Schalter unterschiedlich sind. Es wird empfohlen, den C-Code für NodeJS neu zu schreiben. Wenn es tatsächlich Module gibt, die wiederverwendet werden müssen, können Sie erwägen, den bekannten gcc zu verwenden, um ihn in eine dynamische Linkbibliothek zu kompilieren, und dann eine kleine Menge Code schreiben, um den dynamischen Link zu verwenden Bibliothek und verwenden Sie dann gyp, um diesen Teil des Codes für die Verwendung durch NodeJS zu kompilieren.

Geben Sie den Projektordner ein und führen Sie npm init aus, um das Projekt zu initialisieren. Um nodejs mitzuteilen, dass wir ein Add-on erstellen möchten, müssen wir package.json hinzufügen:


Code kopieren Der Code lautet wie folgt:
„gyp-file“: true

Wenn Sie gcc verwendet haben, müssen Sie sich das Makefile merken. In ähnlicher Weise beschreibt Gyp auch die Kompilierungskonfiguration über eine Datei. Diese Datei ist binding.gyp, eine JSON-Datei, mit der wir sehr vertraut sind. gyp steht nicht im Mittelpunkt unserer Diskussion, daher wird binding.gyp nicht eingehend untersucht. Wir werden uns nur auf die wichtigsten Konfigurationselemente konzentrieren. Hier ist ein Beispiel einer einfachen, aber vollständigen binding.gyp-Datei:


Code kopieren Der Code lautet wie folgt:
{
„Ziele“: [
{
„target_name“: „Hallo“,
„Quellen“: [ „hello.cc“ ],
„include_dirs“: [
" ]
}
]
}


Schauen Sie sich einfach die drei beteiligten Konfigurationselemente an:

1.target_name: Gibt den Namen des Ausgabemoduls an.
2.Quellen: Gibt den Quellcodepfad an, der kompiliert werden muss. Dies ist ein Array.
3.include_dirs: Gibt die Verzeichnisse an, die während des Kompilierungsprozesses verwendet werden sollen. Die Header-Dateien in diesen Verzeichnissen können in der Vorkompilierungsanweisung #include durchsucht werden. Hier wird eine ganz besondere Schreibweise verwendet, anstatt den Pfad als String-Konstante anzugeben. Wir werden später über die Nan-Bibliothek sprechen Schauen Sie sich an, was dieser Befehl ausgibt: node_modulesnan. Es stellt sich heraus, dass dieser Befehl bedeutet, den Pfad der Nan-Bibliothek zurückzugeben.

C-Kodierung

OK, jetzt, da der Quellcode hello.cc konfiguriert wurde, erstellen Sie eine solche Datei. Es gibt ein Problem, an das wir im Voraus erinnern müssen. Das von uns geschriebene C-Modul wird letztendlich von der v8-Engine verwendet, sodass die API, die Schreibmethode usw. durch die v8-Engine eingeschränkt werden. Verschiedene Versionen von NodeJS verwenden tatsächlich unterschiedliche Versionen der v8-Engine, was bedeutet, dass es schwierig ist, einen Satz C-Code zu verwenden, um verschiedene Versionen von NodeJS zu erfüllen (bezogen auf den Kompilierungsprozess). Nach Abschluss der Kompilierung sollte dies möglich sein Ja, Github kann keine Binärbibliotheken hochladen, daher kann npm Binärbibliotheken direkt hochladen und der Kompilierungsschritt ist relativ gering.

Knoten 0.11 und höher:

Code kopieren Der Code lautet wie folgt:

#include
#include

unter Verwendung des Namespace v8;

void SleepFunc(const v8::FunctionCallbackInfo& args) {
Isolate* Isolate = Isolate::GetCurrent();
HandleScope-Bereich (isoliert);
double arg0 = args[0] -> NumberValue();
Sleep(arg0);
}

void Init(Handle exports) {
Isolate* Isolate = Isolate::GetCurrent();
exports->Set(String::NewFromUtf8(isolate, "sleep"),
FunctionTemplate::New(isolate, SleepFunc)->GetFunction());
}

NODE_MODULE(Hallo, Init);

Knoten 0.10 und niedriger:

Code kopieren Der Code lautet wie folgt:

#include
#include

unter Verwendung des Namespace v8;

Handle SleepFun(const Arguments& args) {
HandleScope-Bereich;
double arg0 = args[0] -> NumberValue();
Sleep(arg0);
Gibt Scope.Close(Undefiniert());
zurück }

void Init(Handle exports) {
exports->Set(String::NewSymbol("sleep"),
FunctionTemplate::New(SleepFun)->GetFunction());
}

NODE_MODULE(Hallo, Init);


Man erkennt, dass die Veränderungen noch recht groß sind. Es wäre toll, wenn diese Unterschiede irgendwie abgeschirmt werden könnten. Ich schreibe so viel, nur um Ihnen zu sagen, dass es einen Weg gibt. Es ist Zeit, die Nan-Bibliothek zu besuchen.

nan

Denken Sie daran, dass wir in binding.gyp den Pfad der Nan-Bibliothek eingeführt haben, der hier verwendet werden soll. Wozu dient die Nan-Bibliothek? Es bietet eine Abstraktionsebene, die die Syntaxunterschiede zwischen NodeJS 0.8, NodeJS 0.10, NodeJS 0.12 und dem Add-on vor io.js abschirmt. Lob!

Zuerst installieren: npm install --save nan und sehen, wie die gleiche Funktion nach der Verwendung von nan implementiert wird:

Code kopieren Der Code lautet wie folgt:

#include
unter Verwendung des Namespace v8;

NAN_METHOD(Sleep){
NanScope();
Double arg0=args[0]->NumberValue();
Sleep(arg0);
NanReturnUndefined();
}

void Init(Handle exports){
exports->Set(NanSymbol("sleep"), FunctionTemplate::New(Sleep)->GetFunction());
}

NODE_MODULE(Hallo, Init);

Was Sie wissen müssen, ist das Nan-Set. Was das v8-Set betrifft, müssen Sie nicht darauf achten.

Blick von unten nach oben:

Code kopieren Der Code lautet wie folgt:

NODE_MODULE(Hallo, Init);

Dieser Satz definiert den Eingang des Add-ons. Beachten Sie, dass der erste Parameter mit unserem Zielnamen in binding.gyp übereinstimmen muss. Der zweite Parameter ist die Eingabefunktion des Addons.

Code kopieren Der Code lautet wie folgt:

void Init(Handle exports){
exports->Set(NanSymbol("sleep"), FunctionTemplate::New(Sleep)->GetFunction());
}

Dieser Code ist die Eingabemethode des Add-ons. Es erhält zwei Parameter, nämlich Exporte und Modul. Im obigen Beispiel wird der zweite Parameter weggelassen. Wenn das Modul ein Objekt bereitstellt, können Sie den Schlüsselwert, der für Exporte bereitgestellt werden soll, wie im Beispiel direkt angeben. Wenn es speziell ist und nur einen Wert oder eine Funktion bereitstellt, müssen Sie den zweiten Parameter verwenden, ähnlich wie im Beispiel NODE_SET_METHOD(module, "exports", foo); In diesem Beispiel bedeutet es, ein solches Modul auszugeben:

Code kopieren Der Code lautet wie folgt:

{
„Schlaf“: Schlaf
}

Schlaf ist eine Funktion. Werfen wir einen Blick auf die Definition von Schlaf:

Code kopieren Der Code lautet wie folgt:

NAN_METHOD(Schlaf){
NanScope();
Double arg0=args[0]->NumberValue();
Sleep(arg0);
NanReturnUndefined();
}

Tatsächlich werden die von Javascript übergebenen Parameter gelesen, in einen Doppeltyp konvertiert und dann die Schlafmethode von c aufgerufen.

Addon kompilieren

Jetzt beginnen wir mit der Zusammenstellung dieses Moduls. Führen Sie zunächst „node-gyp configure“ aus, um den Build vorzubereiten. Dadurch werden ein Build-Ordner und einige Dateien generiert. Führen Sie als Nächstes „node-gyp build“ aus, um die Kompilierung zu starten. In diesem Beispiel wird schließlich eine hello.node-Datei im Verzeichnis /build/Release/ generiert, bei dem es sich um das Add-on-Modul handelt, auf das schließlich Javascript verweisen kann.

Wenn später Änderungen am C-Code vorgenommen werden, ist es nicht erforderlich, „node-gyp configure“ auszuführen, sondern einfach „node-gyp build“ direkt auszuführen.

nodejs verwenden

Erstellen Sie eine index.js und sehen Sie, wie Sie dieses Modul verwenden:

Code kopieren Der Code lautet wie folgt:

var sleep=require('./build/Release/hello.node').sleep;

console.log(neues Datum);
schlafen(1000);
console.log(neues Datum);

// Ergebnis
// Mittwoch, 4. März 2015, 14:55:18 GMT 0800 (China Standard Time)
// Mittwoch, 4. März 2015, 14:55:19 Uhr GMT 0800 (China Standard Time)  

C'est très simple, c'est exactement la même chose que d'utiliser des fonctions javascript ordinaires.

À ce stade, les points techniques que je souhaite partager dans cet article ont été expliqués. Mais... en quoi est-ce différent de la méthode proposée au début ? Je ne prendrai pas de captures d'écran, expliquez simplement les résultats directement :

Étant donné que la méthode complémentaire utilise la suspension des threads, il n'y aura théoriquement aucune modification de l'utilisation du processeur ni de la mémoire, et les résultats le vérifient également. Regardons la façon dont les boucles JavaScript simulent le sommeil. Puisque la boucle est toujours en cours d'exécution, il est compréhensible que la mémoire augmente un peu. Ce n'est pas grave si l'on considère l'utilisation du processeur de 25 %, cela semble tout à fait acceptable. Est-ce vraiment le cas ? Le moment est venu que la vérité soit révélée. Le processeur de l'ordinateur portable que j'ai testé est double cœur et quatre threads. Combiné avec une utilisation du processeur de 25 %... l'un des threads double cœur et quatre threads pourrait-il être occupé par cette veille ? En fait, j'ai constaté qu'aucun thread n'était verrouillé pendant cette période, mais ce n'est pas le résultat de JavaScript, mais le mérite d'Intel Hyper-Threading. Parce qu'il est dit qu'il s'agit de quatre threads, l'essentiel est que les deux cœurs de traitement ne peuvent être que des threads doubles, mais le processeur fait un petit tour de coupe de tranche de temps. Par exemple, le noyau cpu01 est divisé en t0 et t2. Supposons que dans un tick après n ticks (cycle de planification), la tâche sera affectée à t0, puis au tick suivant, la tâche sera affectée à t2. Par conséquent, sur une échelle de temps relativement longue (par rapport à la période de planification), la durée d’exécution d’une tâche à t0 et t2 est fondamentalement la même. La situation présentée est donc que le processus nodejs n'occupe pas t0 ou t2 à 100 %, mais occupe respectivement environ 50 %. Étant donné que la planification des processus de Windows est relativement complexe, l'utilisation du processeur fluctue considérablement. On peut prédire que si un processeur double cœur et double thread est utilisé pour traiter ce script, l'utilisation du processeur atteindra 50 % et un cœur sera bloqué. S'il est traité par un processeur monocœur, le processeur passera soudainement à 100 %.

Il semble que la section CPU parle un peu trop, et la section hyper-threading n'est que de la spéculation.

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage