Таймеры
Node.js реализованы очень эффективно. Их реализация (описанная в подробной статье о том, как они работают) может легко обрабатывать очень большое количество таймеров.
Они хранятся в двусвязном списке, который отсортирован, и только следующий таймер для запуска имеет фактический системный таймер libuv, связанный с ним. Когда этот таймер срабатывает или отменяется, следующий в списке становится тем, который привязан к реальному системному таймеру libuv. Когда установлен новый таймер, он просто вставляется в отсортированный список и, если только он не станет следующим, он просто сидит в списке, ожидая своей очереди на следующий. Вы можете иметь тысячи таких очень эффективно.
Вот пара ресурсов о том, как работают эти таймеры:
Сколько одновременных setTimeouts до проблем с производительностью?
Как nodejs внутренне управляет таймерами
Первая ссылка содержит кучу комментариев из фактического кода nodejs, который описывает, как работает система связанных списков таймеров и что она оптимизирует for.
Во второй статье дается более подробное описание того, как оно организовано.
Существуют и другие преимущества, заключающиеся в том, что когда один таймер попадает в начало списка и срабатывает, то после вызова этого обратного вызова node.js проверяет начало списка на наличие любых других таймеров, которые теперь готовы к огонь тоже. Это сместит все другие таймеры с тем же «целевым временем», что и первое, а также любые другие таймеры, которые должны были быть выполнены, пока выполнялись эти различные другие обратные вызовы.
Если у вас есть тысячи, это займет немного больше времени вставить новый таймер в отсортированный связанный список, если там много таймеров, но как только он будет вставлен, вряд ли вообще будет иметь значение, сколько их, потому что он смотрит только на следующий, который срабатывает. Таким образом, процесс ожидания с ожидающими даже десятками тысяч таймеров - это всего лишь один системный таймер (представляющий следующее событие таймера для запуска) и набор данных. Все эти данные для других будущих таймеров не стоят вам ничего, просто сидят там.
Для Javascript, аналогично первому решению python, я мог бы создать столько setTimeouts, сколько необходимо, но проблема в том, что все таймауты работают в основном потоке, но, как я уже сказал, задачи не ресурсоемки, и мне нужна только точность до второго.
Мне кажется, что nodejs может нормально обработать ваше количество setTimeout()
звонков. Если у вас возникла проблема в node.js, это произошло бы не из-за количества таймеров, но вы должны быть уверены, что применили к проблеме достаточное количество ЦП, если у вас есть больше работы для обработки, чем может обработать одно ядро. Вы можете расширить использование ядра с помощью кластеризации nodejs или рабочей очереди, которая использует рабочие потоки или другие процессы nodejs, чтобы помочь с обработкой. node.js сам по себе очень эффективен для всего, что связано с вводом / выводом, так что, пока вы не выполняете масштабных вычислений, интенсивно использующих процессор, один поток node.js может обрабатывать много событий.
Имейте в виду, что Javascript таймеры не дают никаких гарантий точности. Если вы перегружаете процессор, некоторые таймеры сработают позже, чем запланировано, потому что они не являются приоритетными. Но если ваши задачи не сильно нагружают процессор, тогда у вас все будет хорошо.