Node.js optimieren

Vieleicht fehlt mir die Erfahrung und ich merke es erst im Nachhinein, von Komplexsitaet gesehen sehe ich keine Schwierigkeiten, weil ich habe zur Zeit einfach alles in der index.js Datei die hat jetzt schon 10 tausend Zeilen und wenn ich nur den teil fuer Exchanges APIs lesen da raus nehme dann ist es im prinzip aufgeraeumter.

Das lesen der Exchanges APIs soll spaeter fuer bis zu 100 Kontos gleichzeittig funktionieren koennen, weil ich habe eine Art Tradekopierer gebaut, das heist es wird die ganze Zeit nachgeschaut bei den Kunden Kontos ist der Trade offen usw. und ich sehe da irgendwie kein Nachteil ein Wroker zu benutzen das sind ja schon eine Menge Aufgaben die nicht unbedingt in der Main Thread datei ablaufen muessen.

Danach wenn der Kopierer fertig gebaut ist will ich noch Signale erstellen, das heist es sollen eine Menge Charts die agnze Zeit durchgeschaut werden das sind auch alles Aufgaben wo doch sowas wie ein Worker thread optimal fuer ist.

Aber ich glaube eure Meinung zu den Worker Threads ist jetzt so das ihr meint man brauch es nicht nur um ein Exchange Konto zu lesen oder? Da gebe ich euch natuerlich Recht, wenn man nur ein Exchange Konto lesen will waere es unnoetig viel Aufwand ein Worker thread zu erstellen, aber ich probiere zur Zeit so eine Art Tradingapp zu bauen und die soll im Prinzip viele Kontos gleichzeittig behandeln koennen und verschiedene Charts anschauen usw und ich will da schon die besten Techniken einsetzen damit man spaeter weniger Arbeit hat wenn alles gut funktioniert.
 
Ich habe jetzt gerade beim coden kapiert was ihr meint warum diese worker threads nutzlos sind, weil ich gerade probierte ein globales Objekt wo circa hundert Kunden gespeichert sind ueber diese beiden threads zu updaten, ich dachte anfangs Node.js wird die Objekte selber updaten, also was man in ein Thread aendert am Objekt auch direkt im anderen, aber nun sehe ich so funktioniert es nicht.

Wenn ich das globale Objekt in beiden Threads auf gleichen Stand halten will muss ich es die ganze Zeit hin und her kopieren, wenn ein Kunde tausend geschlossene trades hat und tausend orders und nun haben wir hundert kunden und nun sende jede sekunde dieses objekt hin und her, das nutzt ja nichts.
 
Hat jemand Erfahrunngen mit dem Javascript code "setImmediate(callback)" ich habe gestern diese Funktion gesehen in einem Blogbeitrag und so wie es sich anhoerte kann man damit auch bisjen den Ablauf beschleunigen, ich bin mir aber nicht so sicher ob ich es richtig verstanden habe.
 
Wieso sollte es den Ablauf beschleunigen? setImmediate ist eine von vielen Möglichkeiten ein wenig zu beeinflussen, was als nächstes von der Event-Loop bearbeitet wird. Wenn sich dadurch plötzlich der Gesamtablauf beschleunigt, liegt das Problem eher im restlichen Design als dass die reine Verwendung von setImmediate etwas beschleunigt hat.

Alles was du schreibst, scheint eher darauf hin zu deuten, dass du bisher noch nicht wirklich versucht hast zu verstehen, wie NodeJS intern funktioniert oder nachzuvollziehen, wie man Code, z.B. durch die Verwendung von Modulen, besser strukturieren kann oder wie man in JavaScript durch Events und Callbacks komplexe Vorgänge voneinander entkoppeln kann ohne permanent große Datenstrukturen (oder ganze Kontexte) austauschen zu müssen.
 
  • Gefällt mir
Reaktionen: mibbio
Ich hatte so ein Beispiel gesehen wo jemand im Blog was schreibt zu der Funktion das es hilft den naechsten Code aus zu fuehren ohne zu warten, also zur Zeit probiere ich Optimieren zu lernen, du hast da Recht ich kenne mich zur Zeit sogut wie gar nicht aus mit solchen Sachen, ich habe bisher nur Sachen gebaut aber jetzt will ich auch lernen wie man optimiert, damit die Sachen die man baut auch was Nutzen.

Hin und wieder frage ich auch ChatGPT der hat ja auf alles eine Antwort, aber er ist halt nicht so gut am Mitdenken, ich hatte ihn gefragt ist es eine gute Idee Worker threads zu benutzen um Arbeit aus zu lasten das Lesen von Exchanges API und da meint er direkt ja gute Idee usw und die Leute im Forum hatten mir erklaert das es nicht viel Nutzt und ich habe es dann auch gestern erst verstanden warum es nicht viel Nutzt als ich probiere globale Objekte mit daten zu fuelen da bemerkte ich erst wie nutzlos es ist dieses Objekt die ganze Zeit zwischen den threads hin und her zu senden, ja und so lernt man halt was dazu.

Ich habe auch ein paar gute Sachen von den Leuten im Forum hier bereits gelernt und probiere halt noch weiter zu lernen.

Eine Frage zu folgenden Code:


Javascript:
//Beispiel 1 asynchrone Aufruf von zwei Funktionen ohne await
const promise1 = CryptoExchangeKontosLesen();
const promise2 = CryptoPositionenCheck();

promise1.then(result1 => {
}).catch(error => {
});

promise2.then(result2 => {
}).catch(error => {
});

// Der restliche Code wird hier sofort fortgesetzt, ohne auf die Promises zu warten

//Beispiel 2 asynchrone Aufruf von zwei Funktionen mit await

await Promise.all([
                 CryptoExchangeKontosLesen(),
                 CryptoPositionenCheck()
                 ]);

Gibt es ein Unterschied zwischen den beiden Aufrufen in meinem Beispiel? ChatGPT sagt bei dem ersten Beispiel wird nicht gewartet der nachfolgende Code wird weiter ausgefuehrt und beim ersten Beispiel wird auf await promise gewartet.

Was ich erreichen will ist das Funktionen gleichzeittig parallel aufgerufen werden ohne das der Ablauf des Codes durch warten auf Rueckgaben blockiert wird, kann mir jemand dabei helfen das zu verstehen, wie man das richtig aufbaut. Bisher habe ich immer gedacht wenn ich eine Javascript Funktion mit await oder fetch ausfuehre dann wird es immer asynchron ablaufen und der restliche Code wird weiter ausgefuehrt, aber irgendwie habe ich da bemerkt das es nicht immer so ist und oft auch auf die Rueckgabe von einem API Server oder aehnliches gewartet wird bis dann der nachfolgende Code ausgefuehrt wird das ist etwas was ich noch besser lernen will.
 
Ja korrekt, wenn du mit setImmediate eine Funktion registrierst, wird diese als nächstes von der Event-Loop verarbeitet. Dafür wird dann irgendwas anderes warten müssen. NodeJS setzt auf der V8 Engine auf und die arbeitet - wie die meisten JS-Engines - Single-Threaded. Durch die Event-Loop und die Ausführungsgeschwindigkeit der meisten Funktionen wirkt es für uns so, als ob Vieles parallel geschieht, tut es aber nicht.

Was deine beiden Beispiele angeht:

Du hast 2 Promises, dahinter stecken auch Funktionen, welche irgendwann, asynchron von der Event-Loop verabeitet werden. Hier gelten einige Konventionen. Wie z.B. dass bei einer erfolgreichen Ausführung die Funktion, welche über then (als erster Parameter) registiert wird, mit dem erfolgreichen Ergebnis der im Promise verpackten Funktion, aufgerufen wird. Ob das erste Promise oder das zweite dabei zuerst fertig wird, ist vorher nicht festgelegt.

Wenn du nun aber das Schlüsselwort await ins Spiel bringst, kommen wieder mehrere Besonderheiten zusammen, bei denen ein gewisses Verständnis der Event-Loop hilft. Im Grunde steht dort "Liebe Event-Loop: Wenn alle Promises, die ich dir in Promise.all mitteile, aufgelöst sind, mache hier weiter.". Die Event-Loop darf hier also erst mal andere Aufgaben abarbeiten, bevor es weitergeht.

Dabei entspricht

Code:
await Promise.all([
    CryptoExchangeKontosLesen(),
    CryptoPositionenCheck()
]);

Code:
Promise.all([
    CryptoExchangeKontosLesen(),
    CryptoPositionenCheck()
]).then(() => {
...
});

async / await wird häufig genutzt, um asynchronen Code so zu schreiben, dass sich dieser wie synchron ausgeführter Code liest und weitestgehend auch so verhält, was oft beim Verständnis von Code helfen kann, da Promises schnell das Problem haben, dass diese immer tiefer verschachtelt werden, wenn man Abläufe hat, die auf mehrere Schritte aufbauen. Wichtig: Asynchron bedeutet nicht zwangsweise auch parallel.

ChatGPT fragen, ist ganz okay, wenn man bereits ein gewisses Verständnis über das hat, was man macht bzw. formulieren kann, was man benötigt. Da ChatGPT aber selbst nicht versteht was es da macht und die Antworten einfach nur die wahrscheinlichsten zur Fragestellung passenden Antworten sind, kann man damit zwar sehr gut Code-Schnipsel erzeugen, aber ob diese auch das machen würden, was sie sollen, muss man immer noch selbst beurteilen und verstehen.

Wenn du wirklich echte Parallelität benötigst, sind in NodeJS Worker Threads wirklich noch das, was Multi-Threading am nächsten kommt. Und die sind sehr wohl sinnvoll. Wenn du hier aber globale Objekte über Thread-Grenzen hinweg schickst und nicht nur essentiell benötigte Daten austauschst, liegt das Problem nicht in den Worker Threads, sondern deinem Ansatz mit diesen zu arbeiten. Fragen, welche hier zu klären wären, wären aus meiner Sicht:

  • Wer soll Aufgaben an Worker-Threads abgeben?
  • Was sollen die Worker-Threads machen?
  • Welche Informationen benötigen diese, um ihre Aufgabe zu erledigen?
  • Welche Ergebnisse sollen die Worker-Threads liefern?
  • Wer ist an den Ergebnissen interessiert?
 
JP-M schrieb:
  • Wer soll Aufgaben an Worker-Threads abgeben?
  • Was sollen die Worker-Threads machen?
  • Welche Informationen benötigen diese, um ihre Aufgabe zu erledigen?
  • Welche Ergebnisse sollen die Worker-Threads liefern?
  • Wer ist an den Ergebnissen interessiert?
1. Die index.js beinhaltet zur Zeit den kompletten Code meiner Tradingapp, das sind jetzt cica 10 Tausend Zeilen, neben verschiedenen Routern habe ich einige Intervalfunktionen welche die APIs von Exchanges abfragen nach Kontodaten offene und geschlossene Trades. Ich dachte mir ich will da etwas Arbeit vond er index.js an ein Worker Thread abgeben, aber das war problematisch weil der Aufbau meiner index.js datei ist jetzt so dort ist ein globales Objekt namens "Kunden" dort stehen zum Beispiel auch alle offenen und geshclossenen Trades der Kunden drine, wenn man jetzt pro Kunde schon tausend Trades hat dann wird dieses objekt schon ziemlich gros sein und wenn ich dieses objekt jetzt jede Sekunde zum Worker thread sende und dann von dort wieder zurueck zum Hauptthread dann denke ich wird es nicht viel Nutzen also da spare ich dann wahrschienlich nicht viel Resourcen und mache den Aufbau nur komplizierter und verbrauche wahrscheinlich sogar mehr Resourcen.

2. Die Worker threads waeren eigentlich super geeignet fuer viele verschiedene Aufgaben, Charts anamysieren, Kontodaten elsen usw, jedoch ist der derzeitige Aufbau meiner Tradingapp so das vieles ueber globale Objekte laeuft, die Router welche von der Tradingapp angesprochen werden lesen und schreiben daten in diese globalen Objekte und auch die Intervalfunktionen lesen und schreiben dort mit diesen globalen Objekten und wenn ich jetzt Worker threads benutzen will dann habe ich das Problem mit diesen globalen Objekten die brauche ich in der index.js Datei und das hin und her senden der Objkete zwischen Worker threads und Hauptthread verbraucht wahrscheinlich mehr Resourcen als man einspart.

3. Im Prinzip sind es die globalen Objekte die benoietigt werden in beiden threads damit alle Aufgaben gut erledigt werden, die Aufgabe ist im Prinzip die globalen objkete up to date zu halten damit die Tradingapp immer auf dem neusten Stand ist

4. Die Worker Threads sollten eiegntlich verschiedene Aufgaben erledigen Crypto Exchanges lesen Kontodaten lesen aber auch Charts analysieren usw

5. Die Ergebnisse sind dann jeweils wichtig fuer die globalen Objekte damit der ganze Ablauf gut funktioniert


Also im Prinzip habe ich da meine globalen Objekte womit ich an jeder Stelle nachschauen kann welchen Stand welches Konto hat, da sollen dann irgendwann auch bis zu hundert Kontos mit der Tradingapp gesteuert werden koennen. Deswegen probiere ich diese Objekte immer up to date zu halten, jede drei Sekunden wird nachgeschaut auf der Exchange wie der Stand ist wieviel Trades sind offen Kontostand usw und dazu probiere ich jetzt bisjen Optimierung zu lernen.

Also das mit dem asynchron und await ist mir immer noch nicht klar, da muss ich wohl einige Test machen, meiner Meinung nach wenn man kein await benutzt dann wird auch nicht gewartet sondern dann gibt es halt bei Callback die Antwort aber wenn man await benutzt wird gewartet bis die Callbacks kommen und das ist das was ich verhindern will dieses warten auf die Callbacks, ich will halt das die Callbacks abgearbeitet werden wan immer die kommen aber bisdahin soll nicht gewartet werden sondern der weitere Code der darunter steht soll abgearbeitet werden.
 
Was async / await und die Promises angeht, wäre es natürlich so, dass wenn du das await in dem vorherigen Beispiel weglässt, dass die Promises dennoch irgendwann ausgeführt werden und nicht gewartet wird. Aber wie gesagt, es wird hier im Gesamtkontext nichts beschleunigt. Egal ob du dann mit setImmediate oder anderen Mitteln trickst, die Event-Loop arbeitet ohne Worker Threads am Ende alles nacheinander ab, ohne bei den Promises eine Reihenfolge zu garantieren. Vor allem dann nicht, wenn man die Loop manipuliert. Je nachdem wie viel Erfahrung man auch mit anderen Programmiersprachen gesammelt hat, ist das - gerade für Anfänger - durchaus schwer zu verstehen. JavaScript wird zwar immer wieder als Sprache für Anfänger empfohlen, aber auf Grund der vielen verschiedenen Ansätze, die hier vermischt werden, ist sie das eigentlich nicht.

Wenn ich mir deine Antworten durchlese, denke ich dein Problem ist weder Code, der nicht parallel ausgeführt wird, oder globale Objekte, die zusammen mit Worker Threads nicht richtig funktionieren, sondern dein Erfahrungsstand im Bereich Programmierung / Softwareentwicklung und die Herangehensweise all die kleinen Teilprobleme, die es für deine Anwendung zu lösen gilt, zu beschreiben und am Ende in strukturierten Code, auf Ebene von Funktionen / Datenstrukturen / Klassen, zu übertragen.

Globale Objekte sind in vielen Fällen ein einfaches Hilfsmittel, um schnell mal Daten zwischen unterschiedlichen Objekten, Funktionen oder Vorgängen zu teilen. Wenn man die Logik jedoch um diese herum baut, hat man ziemlich schnell unnötig komplexe Implementierungen oder schwer anpassbare Funktionen. Wenn man solche globalen Objekte dann auch noch als zentrale Stelle für eine Wissensbasis verwendet, die von beliebig vielen anderen Stellen aus manipuliert werden kann, macht man sich das Leben selbst schwer - vor allem wenn man dann andere, wichtige Konzepte der gewählten Sprache nicht verstanden hat. Streng genommen hast du hier sogar Glück, da du dich unter NodeJS nur begrenzt mit so blöden Dingen wie echte parallele Zugriffe oder Race-Conditions beschäftigen musst, wenn es am Ende um das manipulieren deiner Kundendaten geht.

Die Kundendaten scheinen am besten mit einer Datenbank vergleichbar zu sein, ob diese mit Lösungen wie z.B. SQLite (z.B. mit better-sqlite3) oder POJOs (also ganz einfache JavaScript-Objekte) abgebildetet wird, sei mal dahingestellt. Aber als ersten Schritt würde ich mir überlegen, wie man diese aus der index.js raus bekommt und in ein eigenes Modul auslagert. Und anstatt dann einfach wieder diese Datenbank von außen direkt zugreifbar zu machen, würde ich mir überlegen, welche Interaktionen möglich sein sollen (Datensatz anlegen, Datensatz abfragen, Datensatz aktualisieren ...). Das sollte hoffentlich dazu führen, dass du dir überlegen musst, welche Teildaten eine Funktion - oder am Ende ein Worker Thread - wirklich für die Erledigung einer Aufgabe benötigt und wie Ergebnisse in die Datenbank eingebracht werden. Denn wenn du immer und überall die globalen Objekte hin und her reichst, zeugt das nur davon, dass du dir über solche Fragen bisher keine wirklichen Gedanken gemacht hast. Und das obwohl du ja eigentlich weißt, was du machen willst. Deine Lösung war nur bisher die globalen Objekte, welche ja scheinbar nicht geeignet sind, herumzureichen, womit du direkt viele Folgeprobleme zu lösen hast.
 
Zuletzt bearbeitet:
Ja du hast da schon Recht ich bin da noch zu unerfahren, dies soll im Prinzip meine erste App werden und ich habe mich hier dafuer entschieden nur bei Serverstart Daten aus der Datenbank zu lesen und waehrend der Laufzeit wollte ich alles in Globalen Objekten bereitstellen damit man sich die Datenbankabfragen spart, meine Idee war das alles so schneller funktioneirt.

Wenn die erste Version der App gut funktioniert werde ich vielleicht auch irgendwann eine zweite erstellen und dann noch mehr Sachen optimieren.
 
BTCStorage schrieb:
ich habe mich hier dafuer entschieden nur bei Serverstart Daten aus der Datenbank zu lesen und waehrend der Laufzeit wollte ich alles in Globalen Objekten bereitstellen damit man sich die Datenbankabfragen spart, meine Idee war das alles so schneller funktioneirt.
Eine Datenbank ist genau für Anwendungsfälle wie zeitgleichen Zugriff auf die selbe Datenstruktur und handling von Konflikten entwickelt worden. Und genau der zeitgleiche Zugriff auf die selben Speicherbereiche ist einer der Knackpunkte multithreadfähiger Programmiersprachen und mit ein Grund warum du die Daten zwischen den Workern in JS im kopieren musst.
 
ChatGPT hatte mir auch so ein Beispiel gezeigt wie ich mit einer Datenbank meine Globalen Objekte zwischen den Worker Threads transportieren kann, aber irgendwie will ich nicht die ganze Zeit Datenbankabfragen am laufen haben, frueher habe ich solche Sachen oft gemacht die ganze Zeit in Datenbank schreiben und lesen aber diesmal wollte ich Datenbankabfragen minimieren und Cache benutzen, also ich dachte mir im Prinzip ist es aehnlich wie Cache wenn ich die Daten in Globalen Objekt behalte waehrend der Laufzeit anstatt jedesmal in der Datenbank alles zu lesen, ich speicher hin und wieder Daten auch waehrend der Laufzeit in der Datenbank, aber nur damit die bei Serverstart nicht komplett neu geladen werden muessen von Exchanges usw. Aber ich kann mir auch gut vorstellen das es Experten gibt die eine Datenbankabfrage so gut optimieren koennen das es kaum Probleme gibt.

Wenn ich bisjen mehr Zeit habe und die erste Version der App nicht so laeuft wie vorgestellt koennte ich ja bisjen Umbau planen und dann vielleicht doch Worker Thread nutzen oder im Prinzip werde ich vielleicht auch noch den ein oder anderen Worker Thread noch nutzen, ich habe ja noch nicht alles fertig gebaut und noch einige Sachen geplant zu bauen wo ich dann von Anfang an weis wie ich die Worker Threads nutzen kann worauf man achten muss. Fuer das Kunden Objekt zb ist es mir zu aufwendig, aber ich kann mir gut vorstellen das so ein Worker Thread ganze Zeit Charts analysiert und dann jeweils nur Signale sendet in den Haupthread da muss man ja nicht komplette Kunden Objekt dann hin und her kopieren.

Aufjedenfall lohnt sich der Aufwand gute Sachen zu bauen die man immer wieder verwenden kann, gelernt ist halt gelernt, wenn man etwas gut aufbaut und es stabil laeuft hat man Jahrelang ein Nutzen und die gelernten Techniken kann man auch immer wieder einsetzen.

Ich habe ja anfangs noch komplett die Fehler gehabt in meinem Aufbau da hat die Intervalfunktion bis zu 30 Sekunden gebraucht jetzt habe ich ja wieder meine circa 3 Sekunden Abstaende, Dank eurern Support konnte ich schon wieder gut was dazu lernen.
 
Hallo Leute, ich habe jetzt anstelle von Worker Threads einige Sachen einfach in eigene express Server gepackt, zuvor habe ich alles auf ein Port in einer index.js Datei laufen lassen, aber nun habe ich zb eine neue Datei namens candelsticks.js und dort laeuft alles ueber ein eigenen express Server auf ein anderen port und der Server speichert nun die ganze Zeit Candelstick Daten, ist auch sehr aktiv am Arbeiten und wenn die Webapp Candelsticks brauch kann sie einfach den Server abfragen. Ich habe bemerkt das die Webapp so jetzt auch besser funktioniert, die Wartezeiten sind kuerzer und im Gegensatz zu Worker Threads ist es so wie ich es jetzt aufgebaut habe auch irgendwie leichter erreichbar und alles laeuft auch in seiner eigenen Umgebung und Thread, was denkt ihr habe ich das gut geloest?
 
Ich sehe gerade das jemand hier gestern etwas geschrieben hat aber der Beitrag wurde geleoscht, er hatte geschrieben "Nodejs Security Probleme" usw also es hat sich danach angehoert als ob er Nodejs nicht empfiehlt, sieht das irgend jemand aehnlich?
 
Zurück
Oben