Для предстоящего проекта с node.js мне нужно выполнять различные домашние задания в периодические моменты. В частности, некоторые задачи каждые миллисекунды, другие каждые 20 мс (50 раз в секунду) и третьи каждую секунду. Поэтому я подумал об использовании setInterval(), со смешными результатами: многие вызовы функций были пропущены.node.js: setInterval() пропущенные вызовы
Тест я использовал это следующим образом:
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);
Существует длинный таймер одной секунды и коротким, что можно регулировать с помощью переменной short
, в данном случае 1 мс. Каждую секунду мы печатаем разницу между количеством ожидаемых тиков в коротком цикле и фактическим количеством повторений короткого счетчика.
Вот как он ведет себя, когда короткий таймер 1 мс:
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
Многие вызовы функций пропускаются. Здесь оно составляет 10 мс:
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
Лучше, но примерно один вызов функции пропускается каждую секунду. А в течение 20 мс:
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
Наконец в течение 100 мс:
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
В этом случае он пропускает очень мало звонков (разрыв увеличился до 2 после 33 секунд и 3 после 108 секунд
.Номера отличаются друг от друга, но на удивление согласуются между прогонами: запуск первого теста 1 мс три раза дал задержку через 10 секунд 9267, 9259 и 9253.
Я не нашел ссылок для этой конкретной проблемы. Существует much cited Ressig post и множество связанных с ним вопросов JavaScript, но большинство полагают, что код работает в браузере, а не в node.js.
Теперь о страшном вопросе: что здесь происходит? Просто шутка; очевидно, что вызовы функций пропускаются. Но я не вижу картины. Я думал, что длинные циклы могут препятствовать коротким, но это не имеет никакого смысла в случае 1 мс. Вызов функций короткого цикла не перекрывается, поскольку они просто обновляют переменную, а процесс node.js составляет около 5% CPU даже с коротким циклом в 1 мс. Средняя нагрузка высокая, хотя около 0,50. Я не знаю, почему тысячи звонков очень сильно подчеркивают мою систему, поскольку node.js обрабатывает many more clients perfectly; должно быть верно, что setInterval() is CPU intensive (или я делаю что-то не так).
Очевидным решением является группировка вызовов функций с использованием более длинных таймеров, а затем многократное выполнение коротких циклов для имитации более короткого таймера. Затем используйте длинный цикл как «универсал-метла», который пропускает любые вызовы в нижних интервалах. Пример: настройка 20 мс и 1000 мс setInterval() вызовов. Для вызовов 1 мс: вызовите их 20 раз в обратном вызове 20 мс. Для вызова 1000 мс: проверьте, сколько раз функция 20 мс была вызвана (например, 47), выполните все оставшиеся вызовы (например, 3). Но эта схема будет немного сложной, поскольку вызовы могут накладываться интересными способами; также он не будет регулярным, хотя он может выглядеть так.
Реальный вопрос: возможно ли это сделать лучше, либо с помощью setInterval(), либо с помощью других таймеров в node.js? Заранее спасибо.
Как? Какие таймеры разрешения, библиотека? – alexfernandez
Есть много сценариев таймера высокого разрешения в google.http: //www.sitepoint.com/creation-exact-timers-in-javascript/ – zer02
Это не решит текущую проблему. –