Должен ли я использовать process.nextTick или setImmediate для асинхронной итерации?

Я работаю над библиотекой JavaScript, которая обеспечивает, помимо прочего, отображение/уменьшение функций в последовательностях, которые могут выполняться асинхронно.

A полезная душа на GitHub предположила, что для Node.js я должен использовать process.nextTick, чтобы асинхронные итерации выполнялись так же быстро, как возможное. (В настоящее время библиотека использует setTimeout во всех средах, которые, как я понимаю, являются субоптимальными.) Я довольно неопытен, когда дело доходит до Node, поэтому я читал о том, как работает этот метод, и неясно, я ли это хороший выбор или нет.

В соответствии с ответом на другой вопрос о SO кажется, что в этом случае было бы разумнее использовать setImmediate, поскольку nextTick, по-видимому, скачет перед ожидающими события ввода-вывода, что кажется мне плохо.

Это, по-видимому, подтверждается некоторыми замечаниями в официальном объявлении Node v0.10.0:

В v0.10 обработчики nextTick запускаются сразу после каждого вызова из С++ в JavaScript. Это означает, что, если ваш код JavaScript вызывает process.nextTick, тогда обратный вызов срабатывает, как только код запускается до завершения, но перед возвратом в цикл событий.

Итак, я прав, и асинхронно повторяя последовательности, используя setImmediate? Или лучше был бы nextTick здесь? (В любом случае, ясное объяснение, почему было бы очень благодарно.)

Ответ 1

Некоторые соображения:

Сначала я сделал серьезные тесты, в какой степени setImmediate работает медленнее, чем process.nextTick. Если он не будет (намного) медленнее, я бы пошел на setImmediate сразу, так как это не будет голодать цикл событий.

В node 0.10 есть жесткий предел (1000, см. node.js docs), сколько раз вы можете рекурсивно вызывать nextTick, поэтому вы должны чтобы это не происходило в любом случае. Вам нужно либо выбрать стратегию перед итерацией, либо изменить стратегию во время итерации (при проверке текущего количества итераций).

Если вы выберете process.nextTick по соображениям производительности, вы можете установить настраиваемый жесткий предел для того, сколько раз он выполнял бы process.nextTick в строке, а также переключился на setImmediate. У меня нет опыта работы с серьезными рабочими нагрузками на nodejs, но я думаю, что людям это не понравится, если ваша библиотека делает прерывистый ввод/вывод.

setImmediate, безусловно, будет безопаснее всего.

Что касается браузера: Я не изучал вашу библиотеку, но, поскольку вы на самом деле начинаете с setTimeout, вам может помочь узнать о новых методах задержки при помощи window.postMessage, а что нет. Там есть красивая и маленькая библиотека под названием next-tick (но с другой семантикой, чем node next-tick!), И там cross-browser shim для setImmediate, что довольно тяжело, потому что 1) ему нужно реализовать спецификацию setImmediate (включая возможность отменить запланированные задачи) и 2) она имеет гораздо более широкую совместимость с браузером.

Просмотрите эту демонстрацию асинхронной сортировки, сравнив setImmediate (прокладка) с параметром setTimeout.