Выполняет ли Node.js минимальную задержку для setTimeout?
В браузерах, если вы используете setTimeout
из функции, называемой setTimeout
, будет введена минимальная задержка в 4 мс. Mozilla developer wiki описывает это поведение и упоминает, что он стал стандартизован в HTML5.
Node.js документация для setTimeout
не упоминает о минимальной задержке. Однако документация функции process.nextTick
описывает ее как более эффективную альтернативу setTimeout(fn, 0)
. Это говорит о возможности того, что он более эффективен, потому что он избегает этой задержки. В противном случае setTimeout(fn, 0)
можно было бы оптимизировать, чтобы вести себя одинаково.
Обеспечивает ли Node.js минимальную задержку для setTimeout, как это делают веб-браузеры?
Ответы
Ответ 1
У него нет минимальной задержки, и на самом деле это проблема совместимости между браузерами и node. Таймеры полностью не определены в JavaScript (это спецификация DOM, которая не используется в Node, и даже не отслеживается браузерами) и Node реализует их просто из-за того, насколько они фундаментальны в истории JavaScript и как незаменимы они в противном случае.
Node использует libuv, который представляет собой кросс-платформенный уровень абстракции для системного уровня более низкого уровня, таких как файловая система, сетевые элементы и т.д. Одной из таких задач являются таймеры, которые Node предоставляют минимальную оболочку. На уровне libuv используемыми таймерами являются таймеры высокой точности для конкретной системы. В Windows, например, это реализовано с помощью QueryPerformanceFrequency
и FileTimeToSystemTime
, который обеспечивает разрешение, измеренное в наносекундах.
В Node, если вы укажете setTimeout(callback, 1)
, то он будет выполнен через миллисекунду позже (при условии, что система не задерживает его из-за переполнения). В браузерах минимальное время будет 4 миллисекунды, как указано спецификацией HTML5: https://developer.mozilla.org/en/DOM/window.setTimeout. Это не гарантированное время, как минимум. Ожидается, что большинство браузеров будут иметь разрешение ~ 15 мс, что влияет на анимацию DOM.
Одна действительная часть информации заключается в том, что тайм-ауты, установленные на одну и ту же миллисекунду, в течение того же кадра будут выполняться в том порядке, в котором они были поставлены в очередь. Если вам нужно:
setTimeout(callback1, 1);
setTimeout(callback2, 1);
setTimeout(callback3, 1);
setTimeout(callback4, 1);
Все в одном блоке Node должны вызывать их в этом порядке. Это применимо только в том случае, если у них одинаковое время разрешения.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms644905(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724280(v=vs.85).aspx
Ответ 2
Из этого теста не кажется, что он имеет минимальную задержку.
Если вы выполняете setTimeout()
с длительностью 10ms
и длинным возвращаемым значением в консоли, это то, что вы получаете:
var timer = setTimeout(function(){ console.log(timer);}, 10);
{ _idleTimeout: 10,
_onTimeout: [Function],
_idlePrev: null,
_idleNext: null,
_idleStart: Sun, 28 Aug 2011 14:34:41 GMT }
Аналогично, с продолжительностью 1ms
вы получаете:
var timer = setTimeout(function(){ console.log(timer);}, 1);
{ _idleTimeout: 1,
_onTimeout: [Function],
_idlePrev: null,
_idleNext: null,
_idleStart: Sun, 28 Aug 2011 14:34:59 GMT }
Но если вы выполняете длительность 0
, вы не получаете свойство _idleTimeout:
вообще, что, по-видимому, предполагает, что обратный вызов вызывается немедленно, хотя и асинхронно.
var timer = setTimeout(function(){ console.log(timer);}, 0);
{ repeat: 0, callback: [Function] }
Кроме того, если я делаю просто сравнение даты начала и конца, я обычно получаю 0
как результат вычитания начала с конца.
var start = Date.now();
var timer = setTimeout(function(){ console.log(timer, Date.now() - start );}, 0);
{ repeat: 0, callback: [Function] } 0
Эти тесты проводились с использованием Node.js 0.5.2
.
Ответ 3
Следует отметить, что реализация таймера зависит от операционной системы. Например, я помню "старый добрый" вопрос JTimer, где разрешение таймера составляло 16 мс в Windows и ~ 1 мс на других платформах. Это почти наверняка стоит проверить на вашем конкретном сервере.