Node.js timere er meget effektivt implementeret. Deres implementering (beskrevet i en detaljeret artikel om, hvordan de fungerer) kan nemt håndtere meget store antal timere.
De holdes i en dobbelt linket liste, der er sorteret, og kun den næste timer, der skal fyre, har en faktisk libuv-systemtimer tilknyttet. Når denne timer udløses eller annulleres, bliver den næste på listen den, der er knyttet til en faktisk libuv-systemtimer. Når en ny timer er indstillet, indsættes den bare i den sorterede liste, og medmindre den bliver den næste, der affyres, sætter den sig bare på listen og venter på, at det bliver den næste. Du kan få tusindvis af disse meget effektivt.
Her er et par ressourcer til, hvordan disse timere fungerer:
Hvor mange samtidige setTimeouts før ydeevneproblemer?
Hvordan administrerer nodejs timere internt
Den første reference indeholder en masse kommentarer fra den faktiske nodejs-kode, der beskriver, hvordan det timer-linkede listesystem fungerer, og hvad det er optimeret til.
Den anden artikel giver dig en lidt højere niveaubeskrivelse af, hvordan den er organiseret.
Der er andre effektivitetsgevinster, så når en timer kommer til starten af listen, og den udløses, så tjekker node.js efter at have ringet tilbage, forsiden af listen for andre timere, der nu også er klar til at udløse. Dette vil feje alle andre timere op med den samme "måltid" som den første og også alle andre, der er kommet forfalden, mens disse forskellige andre tilbagekald kørte.
Når du har tusindvis, vil det tage lidt længere tid at indsætte en ny timer i den sorterede linkede liste, hvis der er mange timere derinde, men når først den er indsat, er det næsten ligegyldigt, hvor mange der er, fordi den kun kigger på den næste til at fyre. Så processen med at sidde der med endda titusindvis af timere afventende er kun én systemtimer (repræsenterer den næste timerhændelse, der udløses) og en masse data. Alle de data for de andre fremtidige timere koster dig ikke noget bare at sidde der.
For Javascript, svarende til pythonens første løsning, kunne jeg afføde så mange setTimeouts som nødvendigt, men problemet er, at alle timeouts fungerer på hovedtråden, men som sagt, opgaverne er ikke ressourcekrævende, og jeg har kun brug for nøjagtighed til sekund.
Det forekommer mig, at nodejs kunne håndtere din mængde setTimeout()
ringer fint. Hvis du havde et problem i node.js, ville det ikke være på grund af antallet af timere, men du skulle være sikker på, at du anvender nok CPU på problemet, hvis du har mere arbejde at behandle, end én kerne kan håndtere. Du kan udvide kernebrugen med nodejs-klynger eller med en arbejdskø, der bruger Worker Threads eller andre nodejs-processer til at hjælpe med behandlingen. node.js er i sig selv meget effektiv med alt I/O-relateret, så så længe du ikke laver større CPU-intensive beregninger, kan en enkelt node.js-tråd håndtere en masse hændelsesbehandling.
Husk, at Javascript-timere ikke giver nogen garanti for nøjagtighed. Hvis du roder CPU'en ned, vil nogle timere udløses senere end planlagt, fordi de ikke er forebyggende. Men hvis dine opgaver ikke er CPU-intensive, så har du det måske helt fint.