10

I'm working on a JavaScript library that provides, among other things, map/reduce functions on sequences that can be iterated asynchronously.

A helpful soul on GitHub suggested that for Node.js, I should use process.nextTick to make asynchronous iterations as fast as possible. (The library currently uses setTimeout in all environments, which I do understand is suboptimal.) I'm pretty inexperienced when it comes to Node, so I was reading up on how this method works and it isn't clear to me whether it's a good choice or not.

According to the answer to another question on SO, it seems that it would probably make more sense to use setImmediate in this case as nextTick apparently jumps ahead of pending I/O events, which seems bad to me.

This appears to be corroborated by some remarks in the official Node v0.10.0 announcment:

In v0.10, nextTick handlers are run right after each call from C++ into JavaScript. That means that, if your JavaScript code calls process.nextTick, then the callback will fire as soon as the code runs to completion, but before going back to the event loop.

So am I right, and iterating over sequences asynchronously should be done with setImmediate? Or would nextTick be a better choice here? (In either case, a clear explanation why would be much appreciated.)

Community
  • 1
  • 1
Dan Tao
  • 125,917
  • 54
  • 300
  • 447
  • Why exactly do you need "asynchronous iteration"? – Myrne Stol May 23 '13 at 13:36
  • suppose you have a long list of data items that needs to get some kind of expensive processing applied, item by item. using `nextTick`/ `setImmediate` will allow other code to run in between each processing step, thus potentially preserving the capability to e.g. response to a HTTP request or, say, user interaction with the GUI. – flow Sep 10 '13 at 14:55

1 Answers1

10

Some considerations:

I'd first do serious benchmarks to what extend setImmediate is slower than process.nextTick. If it's not (much) slower, I'd go for setImmediate straight away since that won't starve the event loop.

In node 0.10 there's a hard limit (1000, see node.js docs) to how many times you can recursively call nextTick, so you should prevent that from happening in any case. You either need to choose a strategy before iteration, or be able to change strategy during iteration (while checking for current iteration count).

If you choose process.nextTick for performance reasons, you might want to set a configurable hard limit for how many times it would do process.nextTick in a row, and else switch to setImmediate. I don't have experience with serious work loads on nodejs, but I do think people are not gonna like it if your library makes their I/O choppy.

setImmediate would certainly be safest, all in all.

As for the browser: I haven't studied your library, but since you are actually coming from setTimeout, you may be helped learning about the new breed of delay techniques via window.postMessage and what not. There's a nice and small library called next-tick (but with different semantics than node next-tick!) and there's a cross-browser shim for setImmediate, which is quite a bit heavier because 1) it needs to implement the setImmediate spec (including ability to cancel scheduled tasks) and 2) it has much wider browser compatibility.

Check out this async sorting demo comparing setImmediate (shim) to setTimeout.

Myrne Stol
  • 11,222
  • 4
  • 40
  • 48
  • 1
    Even if `nextTick` was considerably faster than `setImmediate` in some way, I think he'd be better off just executing more of the work before calling `setImmediate` again. In the end, there's no point in marshalling code execution if it'll end up blocking everything anyway. – Hristo May 23 '13 at 13:25
  • 1
    @HristoDachev: Good point. But with his question as it stands, it isn't exactly clear why he wants to "asynchronously iterate". Dividing the work into batches which are executed synchronously would lose some of the asynchronousness. If all that's needed is a asynchronous interface for a batch operation, than a single `setImmediate` for the whole amount of work would suffice, making speed differences irrelevant. I'll ask. – Myrne Stol May 23 '13 at 13:35