Node.js-Timer sind sehr effizient implementiert. Ihre Implementierung (in einem ausführlichen Artikel über ihre Funktionsweise beschrieben) kann problemlos mit einer sehr großen Anzahl von Timern umgehen.
Sie werden in einer doppelt verknüpften Liste aufbewahrt, die sortiert ist, und nur dem nächsten Timer, der ausgelöst wird, ist ein tatsächlicher libuv-Systemtimer zugeordnet. Wenn dieser Timer ausgelöst oder abgebrochen wird, wird der nächste in der Liste derjenige, der an einen tatsächlichen libuv-Systemtimer angehängt ist. Wenn ein neuer Timer eingestellt wird, wird er einfach in die sortierte Liste eingefügt, und wenn er nicht der nächste ist, der ausgelöst wird, sitzt er einfach in der Liste und wartet darauf, dass er als Nächster an der Reihe ist. Sie können Tausende davon sehr effizient haben.
Hier sind ein paar Ressourcen zur Funktionsweise dieser Timer:
Wie viele gleichzeitige setTimeouts vor Leistungsproblemen?
Wie verwaltet nodejs Timer intern
Die erste Referenz enthält eine Reihe von Kommentaren aus dem eigentlichen nodejs-Code, die beschreiben, wie das Timer-Linked-List-System funktioniert und wofür es optimiert ist.
Der zweite Artikel gibt Ihnen eine etwas höhere Beschreibung, wie es organisiert ist.
Es gibt andere Effizienzen, so dass, wenn ein Timer an den Anfang der Liste gelangt und ausgelöst wird, node.js nach dem Aufrufen dieses Rückrufs den Anfang der Liste auf andere Timer überprüft, die jetzt ebenfalls zum Auslösen bereit sind. Dadurch werden alle anderen Timer mit der gleichen "Zielzeit" wie der erste und auch alle anderen, die fällig wurden, während diese verschiedenen anderen Rückrufe liefen, aufgeräumt.
Wenn Sie Tausende haben, dauert es etwas länger, einen neuen Timer in die sortierte verknüpfte Liste einzufügen, wenn dort viele Timer enthalten sind, aber sobald er eingefügt ist, spielt es kaum eine Rolle, wie viele es gibt, da er immer nur betrachtet wird der nächste, der feuert. Das Sitzen dort mit sogar Zehntausenden anstehenden Timern ist also nur ein System-Timer (der das nächste Timer-Ereignis darstellt, das ausgelöst wird) und eine Menge Daten. All diese Daten für die anderen zukünftigen Timer kosten Sie nichts, wenn Sie nur dasitzen.
Für Javascript könnte ich, ähnlich wie bei der ersten Lösung von Python, so viele setTimeouts wie nötig spawnen, aber das Problem ist, dass alle Timeouts im Hauptthread funktionieren, aber wie gesagt, die Aufgaben sind nicht ressourcenintensiv und ich brauche nur Genauigkeit für die zweitens.
Es scheint mir, dass nodejs Ihre Menge an setTimeout()
verarbeiten könnte ruft einfach gut an. Wenn Sie ein Problem in node.js hätten, wäre es nicht wegen der Anzahl der Timer, aber Sie müssten sicher sein, dass Sie genug CPU auf das Problem anwenden, wenn Sie mehr Arbeit zu verarbeiten haben, als ein Kern verarbeiten kann. Sie könnten die Kernnutzung mit nodejs-Clustering oder mit einer Arbeitswarteschlange erweitern, die Worker-Threads oder andere nodejs-Prozesse verwendet, um die Verarbeitung zu unterstützen. node.js ist an sich sehr effizient bei allem, was mit E/A zu tun hat. Solange Sie also keine großen CPU-intensiven Berechnungen durchführen, kann ein einzelner node.js-Thread eine Menge Ereignisverarbeitung verarbeiten.
Beachten Sie, dass Javascript-Timer keine Genauigkeitsgarantie geben. Wenn Sie die CPU verlangsamen, werden einige Timer später als geplant ausgelöst, da sie nicht präventiv sind. Aber wenn Ihre Aufgaben nicht CPU-intensiv sind, dann sind Sie vielleicht in Ordnung.