Per un progetto imminente con node.js, è necessario eseguire varie attività di manutenzione periodica. In particolare alcuni compiti ogni millisecondo, altri ogni 20 ms (50 volte al secondo) e altri ancora ogni secondo. Così ho pensato di usare setInterval(), con risultati divertenti: molte chiamate di funzione venivano saltate.node.js: setInterval() per saltare le chiamate
Il riferimento I utilizzata è la seguente:
var counter = 0;
var seconds = 0;
var short = 1;
setInterval(function() {
counter ++;
}, short);
setInterval(function() {
seconds ++;
log('Seconds: ' + seconds + ', counter: ' +
counter + ', missed ' +
(seconds * 1000/short - counter));
}, 1000);
C'è un timer lungo di un secondo e un breve che può essere regolata utilizzando la variabile short
, in questo caso 1 ms. Ogni secondo viene stampata la differenza tra il numero di tick previsti nel ciclo breve e il numero effettivo di volte in cui il contatore breve è stato aggiornato.
Ecco come si comporta quando il timer breve è di 1 ms:
2012-09-14T23:03:32.780Z Seconds: 1, counter: 869, missed 131
2012-09-14T23:03:33.780Z Seconds: 2, counter: 1803, missed 197
2012-09-14T23:03:34.781Z Seconds: 3, counter: 2736, missed 264
...
2012-09-14T23:03:41.783Z Seconds: 10, counter: 9267, missed 733
chiamate di funzione Molti sono saltati. Qui è per 10 ms:
2012-09-14T23:01:56.363Z Seconds: 1, counter: 93, missed 7
2012-09-14T23:01:57.363Z Seconds: 2, counter: 192, missed 8
2012-09-14T23:01:58.364Z Seconds: 3, counter: 291, missed 9
...
2012-09-14T23:02:05.364Z Seconds: 10, counter: 986, missed 14
Migliore, ma circa una chiamata di funzione viene saltata ogni secondo. E per 20 ms:
2012-09-14T23:07:18.713Z Seconds: 1, counter: 46, missed 4
2012-09-14T23:07:19.713Z Seconds: 2, counter: 96, missed 4
2012-09-14T23:07:20.712Z Seconds: 3, counter: 146, missed 4
...
2012-09-14T23:07:27.714Z Seconds: 10, counter: 495, missed 5
Infine per 100 ms:
2012-09-14T23:04:25.804Z Seconds: 1, counter: 9, missed 1
2012-09-14T23:04:26.803Z Seconds: 2, counter: 19, missed 1
2012-09-14T23:04:27.804Z Seconds: 3, counter: 29, missed 1
...
2012-09-14T23:04:34.805Z Seconds: 10, counter: 99, missed 1
In questo caso salta pochissimi chiamate (gap aumentata a 2 dopo 33 secondi e 3 dopo 108 secondi
.I numeri variano, ma sono sorprendentemente coerenti tra le esecuzioni: l'esecuzione del primo benchmark 1 ms tre volte ha prodotto un ritardo dopo 10 secondi di 9267, 9259 e 9253.
Non ho trovato riferimenti per questo particolare problema. C'è questo much cited Ressig post e molte domande relative a JavaScript, ma la maggior parte suppone che il codice venga eseguito in un browser e non in node.js.
Ora per la domanda temuta: cosa sta succedendo qui? Solo scherzando; ovviamente le chiamate di funzione vengono saltate. Ma non riesco a vedere lo schema. Ho pensato che i cicli lunghi avrebbero potuto prevenire quelli brevi, ma non ha senso nel caso 1 ms. Le chiamate di funzione a ciclo breve non si sovrappongono poiché aggiornano solo una variabile e il processo node.js è vicino al 5% della CPU anche con un ciclo breve di 1 ms. Il carico medio è alto, tuttavia, a circa 0,50. Non so perché un migliaio di chiamate sottolineano così tanto il mio sistema, dal momento che node.js gestisce many more clients perfectly; deve essere vero che setInterval() is CPU intensive (o sto facendo qualcosa di sbagliato).
Una soluzione ovvia è raggruppare le chiamate di funzione utilizzando i timer più lunghi, quindi eseguire più volte chiamate di funzione a ciclo breve per simulare un timer più breve. Quindi usa il ciclo lungo come "scopa-vagone" che fa perdere le chiamate agli intervalli più bassi. Un esempio: imposta chiamate da 20 ms e 1000 ms setInterval(). Per chiamate da 1 ms: chiamarle 20 volte nel callback di 20 ms. Per la chiamata 1000 ms: controlla quante volte è stata chiamata la funzione 20ms (ad es. 47), fai tutte le chiamate rimanenti (ad esempio 3). Ma questo schema sarà un po 'complesso, dal momento che le chiamate potrebbero sovrapporsi in modi interessanti; inoltre non sarà regolare anche se potrebbe sembrare.
La vera domanda è: può essere fatto meglio, con setInterval() o altri timer all'interno di node.js? Grazie in anticipo.
Come? Quali timer di risoluzione, una libreria? – alexfernandez
Ci sono molti script timer ad alta risoluzione in google.http: //www.sitepoint.it/creating-accurate-timers-in-javascript/ – zer02
Non risolverà il problema attuale. –