> --
> You received this message because you are subscribed to the Google Groups "nodejs" group.
> To post to this group, send email to nod...@googlegroups.com.
> To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
>
If I call process.nextTick() 10 times in a single sync tick, they will all 10 be put onto a queue and at the next available "tick" in the event loop, all 10 callbacks will be called in order with a sync for loop. I recently patched this piece of code to be more performant, so you can now queue up thousands of these with very little overhead. It will be one single entry in the event loop and a single for loop over the callbacks, calling them in order.
setTimeout doesn't have such semantics, it depends on system timers and is much less efficient for things that simple need to be deferred till the next tick.
setTimeout(fn) and process.nextTick(fn) do in fact act different in node, and I have often relied on this difference in the past for various needs.
> BTW, see what I was doing just right now with your code :
>
> process._tickCallback = function (l) {
> if (l= nextTickQueue.length) {
> nextTickQueue.forEach(function (f) { f() });
> nextTickQueue.splice(0, l);
> }
Keep in mind that forEach is much slower than a plain for(;;) loop. This is a core part of node.js and speed really matters here.
> No, because setTimeout means to run the code after AT LEAST the given number of ms. This means it needs to check the clock at least once to see that at least 0 ms have elapsed.
You must be joking :-)
> Sure we could optimize this special case and merge the two. I in fact asked for this about a year ago on this list. I've since realized that it's good to keep it simple and not confuse the meanings. I would like setTimeout to stay pure and not have any hacked optimizations.
But as we've been using setTimeout(,0) for years in the browsers with the exact same meaning that .nextTick() has, why the need for a new verb ?
> setTimeout(fn) and process.nextTick(fn) do in fact act different in node, and I have often relied on this difference in the past for various needs.
This 4 things are afaics what -currently- make a nextTick(f) !== setTimeout(f,0)
-nextTick() doesn't return any reference.
-You can't remove a function once nextTick'ed().
-You can't pass arguments to a nextTicked() function (not that this is a good thing nor very popular).
-setTimeout creates a needless 0ms new process.Timer() to do what nextTick does much better.
My point is that in the head of any web programmer setTimeout(,0) means do this not now but asap, which is exactly === what .nextTick() does.
--
Jorge.
Neither do I, really. But we're very much used to the setTimeout(,0). Why not to "enhance" it as much as we can ? Semantically it's a nexttick...
--
Jorge.
Of course.
--
Jorge.
Even if you put in complex code to optimize setTimeout for the 0ms case, you will still need to implement all the other features of setTimeout for that special case and it will still be much slower.
It's really quite simple, process.nextTick is not a timer. It's a fast, simple, and efficient way to delay some code till the next tick of the event loop. This is a very common need when building async apis like in node.
It will confuse to merge the two meanings into a single function that acts completely different if the value passed in happens to be a 0.
Yep. http://github.com/isaacs/node/blob/master/src/node.js#L589-607
It's a DOM construct, not a JS language construct.
--i
function hello(x) {console.log('hello', x)}
process.nextTick(hello.bind(this, "world"));
--
You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
Oh not a problem at all. Just a thought. I personally don't like having to pass 'this' around with bind but it works well.
I also think nextTick is much clearer. Just because the W3C DOM came first doesn't mean we stop trying new things. In time, I think node will find a good balance of new and old JavaScript practice. No sense in prematurely declaring the one true way.
Brian.
>> nodejs+un...@googlegroups.com<nodejs%2Bunsu...@googlegroups.com>
No, nextTick is ok where it is.
> and force everyone to use the much slower and heavier setTimeout just because that's the only option in the browser?
No. I'm saying that we could improve setTimeout(,0) and make it as fast as it could be. As fast as nextTick.
> Even if you put in complex code to optimize setTimeout for the 0ms case, you will still need to implement all the other features of setTimeout for that special case and it will still be much slower.
Not if we disguise a call to nextTick in that special case (,0).
> It's really quite simple, process.nextTick is not a timer. It's a fast, simple, and efficient way to delay some code till the next tick of the event loop. This is a very common need when building async apis like in node.
Yep. A timer of 0ms isn't really a timer.
> It will confuse to merge the two meanings into a single function that acts completely different if the value passed in happens to be a 0.
It doesn't make much sense to time 0 ms, does it ? IMO setTimeout(,0) should be doing now ~ exactly what nextTick does.
In any case, as talk is cheap, I'll see what code -if any- can I come up with, so that we have something more concrete to discuss.
--
Jorge.
- function applyNext(fn, args, thisp) {
+ function applyNext(fn, thisp, args) {
process.nextTick(function () {
fn.apply(thisp, args);
});
}
function callNext(fn, thisp) {
- applyNext(fn, Array.prototype.slice.call(arguments, 1));
+ applyNext(fn, thisp, Array.prototype.slice.call(arguments, 2));
}
--i
The only thing you have to be careful with is that
setTimeout/setInterval still returns an id that can be cancelled with
clearTimeout (e.g. recall things added with nextTick). Otherwise you
break semantics in a surprising way.
-Vitali
These are obviously simple examples. The truth for mine being that I'm
passing an arg to something else so it just as well could bind
console.log. We do lose some ()'s which is nice, though we still don't
have the ability to bind `this` if that was important. I feel like
this method of argument passing is somewhat outdated now that ES-5 is
taking hold and V8 has started supporting an array of the extensions.
Granted, bind is a little verbose, but there aren't many cases when I
want to pass state and I'm not using a closure or an object for that
state. Threading arguments through calls has always been an annoyance
(I'll blame Haskell for making me picky here with its do syntax).
I'd be fine with seeing these extensions go in provided it doesn't
have a negative impact on performance (not that I have any final word
to say). I do not see myself using them.
Brian.
My understanding that this special role of setTimeout(,0) is an
important part of your belief system => it is a religious question,
which cannot be resolved by a debate.
Nobody can prevent you from using setTimeout(,0) as you please, and if
you want you can clone the project in Github, and change it as you
please too => your implementation will be superior => people will
abandon Node.js and flock to your clone. ;-) There is nothing to discuss
here.
Cheers,
Eugene Lazutkin
http://lazutkin.com/
I have yet to see a good technical reason how setTimeout(, 0) is
expected to have different semantics & why an improvement for it is
not warranted.
Here are the criteria I feel need to be addressed on this topic:
1) Is any current functionality broken by changing this implementation
2) Is the broken functionality perfectly correct code or is it making
assumptions about internal implementation that was never documented.
3) Is the broken functionality in any really visible components?
4) Are the performance benefits likely to be felt wide-spread?
Here's what has been so far:
#1 setTimeout/setInterval returns a cancellable handle - any
optimization via nextTick *must* address this issue. I would prefer
that this solve the issue properly instead of delegating to a wrapper
function that checks whether or not it was cancelled.
#2 is only for code that cancel's said timeout - no expectation on the
relative ordering between setTimeout/setInterval & nextTick is
allowed.
#3 unclear
#4 is yes since many people may write code expecting setTimeout(, 0)
to behave optimally (& there's no reason it shouldn't).
#1 may mean prove to be too difficult to implement cleanly (one
alternative would be to allow a configurable property - e.g.
setTimeout0Turbo(true), although I'm not enamoured with that
particular idea either).
-Vitali
This "problem" is not the most pressing issue with node.js, frankly it
is fairly unimportant by any masure, and I don't see principals leaning
towards "fixing" it --- why waste time? Clone the repo, fix it,
demonstrate that it is superior and be done with it.
Cheers,
Eugene Lazutkin
http://lazutkin.com/
> Eugene please don't jump into a discussion for the purposes of
> starting a flame-war. There's no need to even fork - it's trival to
> write a wrapper within js that accomplishes this application-wide.
> This is a discussion about improving node.js for everyone
> transparently.
>
> I have yet to see a good technical reason how setTimeout(, 0) is
> expected to have different semantics & why an improvement for it is
> not warranted.
>
> Here are the criteria I feel need to be addressed on this topic:
> 1) Is any current functionality broken by changing this implementation
Yes, it breaks semantics if setTimeout fires faster than it does currently. nextTick events are higher priority than timeout events. It's part of node. Changing that would change node and break programs that expect the old behavior.
> 2) Is the broken functionality perfectly correct code or is it making
> assumptions about internal implementation that was never documented.
I think it was documented that process.nextTick has a special place of high priority in the event queue. I know Ryan has said this. From the docs:
> On the next loop around the event loop call this callback. This is not a simple alias to setTimeout(fn, 0), it's much more efficient.
> 3) Is the broken functionality in any really visible components?
Not sure what you mean by this. setTimeout and process.nextTick aren't the same thing.
> 4) Are the performance benefits likely to be felt wide-spread?
Again, I'm not sure what you're asking. People wanting to defer something to the next tick as fast as possible will already be using nextTick. Someone wanting to set a timeout till after a specified time will use setTimeout.
Using setTimeout with a 0 timeout is a very bad idea in most cases. It's rarely the intended effect.
>
> Here's what has been so far:
> #1 setTimeout/setInterval returns a cancellable handle - any
> optimization via nextTick *must* address this issue. I would prefer
> that this solve the issue properly instead of delegating to a wrapper
> function that checks whether or not it was cancelled.
> #2 is only for code that cancel's said timeout - no expectation on the
> relative ordering between setTimeout/setInterval & nextTick is
> allowed.
> #3 unclear
> #4 is yes since many people may write code expecting setTimeout(, 0)
> to behave optimally (& there's no reason it shouldn't).
>
> #1 may mean prove to be too difficult to implement cleanly (one
> alternative would be to allow a configurable property - e.g.
> setTimeout0Turbo(true), although I'm not enamoured with that
> particular idea either).
setTimeout0Turbo(true)? what's wrong with the current simple and very clear API? A timeout is a timeout, pushing something to the next is called nextTick.
I'm all for API's being simple and clean, and before I fully understood the meaning of nextTick I too was fighting to just merge it with setTimeout. Now I realize they are very different things and should stay that way for sanity's sake.
>
> -Vitali
>
Cheers,
Eugene Lazutkin
http://lazutkin.com/
On 08/27/2010 10:36 PM, Marco Rogers wrote:
> Sooo, you want us to stop having an interesting conversation about node
> on a public mailing list created for that purpose, because you decided
> to get full emails instead of a digest? You'll excuse me if I politely
> decline.
>
> Cheers
> :Marco
>
>
> On Fri, Aug 27, 2010 at 11:23 PM, Eugene Lazutkin
> <eugene....@gmail.com
> <mailto:eugene....@gmail.com>> wrote:
> >> setTimeout(, 0) is a hack. Even in the browser it doesn't work as
> >> intended. No need to patch it, when there is a clean alternative:
> >> setTimeout() schedules a function after some delay, nextTick()
> schedules
> >> a function as soon as possible.
> >>
> >> My understanding that this special role of setTimeout(,0) is an
> >> important part of your belief system => it is a religious question,
> >> which cannot be resolved by a debate.
> >>
> >> Nobody can prevent you from using setTimeout(,0) as you please,
> and if
> >> you want you can clone the project in Github, and change it as you
> >> please too => your implementation will be superior => people will
> >> abandon Node.js and flock to your clone. ;-) There is nothing to
> discuss
> >> here.
> >>
> >> Cheers,
> >>
> >> Eugene Lazutkin
> >> http://lazutkin.com/
> >>
> >>
> >> On 08/27/2010 04:25 PM, Jorge wrote:
> >>> On Aug 27, 9:45 pm, Camilo Aguilar
> <cam...@cloudescape.com
> <mailto:nod...@googlegroups.com>.
> >> To unsubscribe from this group, send email to
> nodejs+un...@googlegroups.com
> <mailto:nodejs%2Bunsu...@googlegroups.com>.
> >> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en.
> >>
> >>
> >
>
> --
> You received this message because you are subscribed to the Google
> Groups "nodejs" group.
> To post to this group, send email to
> nod...@googlegroups.com
> <mailto:nod...@googlegroups.com>.
> To unsubscribe from this group, send email to
> nodejs+un...@googlegroups.com
> <mailto:nodejs%2Bunsu...@googlegroups.com>.
> For more options, visit this group at
> http://groups.google.com/group/nodejs?hl=en.
>
>
>
>
> --
> Marco Rogers
> marco....@gmail.com
> <mailto:marco....@gmail.com>
>
> Life is ten percent what happens to you and ninety percent how you
> respond to it.
> - Lou Holtz
>
Cheers,
Eugene Lazutkin
http://lazutkin.com/
--
Jorge.
My preferred idea would be to either figure out some way of storing it
in a map so that it's O(1) to insert & remove or store the index as
part of the object you return from nextTick & then updating all the
indexes through the array element references on removal (less ideal).
-Vitali
2010/8/29 Scott González <scott.g...@gmail.com>:
1) Does it significantly complicate code for no benefit
2) Does it break existing functionality
3) Is the code legible & meet qualitative standards (e.g. spaghetti
code or well-written & well-designed code)
I think there's nothing fundamentally wrong with the patch - it just
needs some minor tweaks & a more thorough code review.
-Vitali
Why complicate the code for a use case that shouldn't exist? Namely using setTimeout when you really mean nextTick.
Even if someone provides a patch it still has to be maintained. This is not without cost and very little gain if any.
Sent from my Nexus One
> I'd prefer it called process.removeNextTick - I think it makes sense
> to keep this legible.
No problem. It's that I like the C standard library's naming-style : rmvNxtTick :-)
nextTick items can be removed too with clearInterval/timeout(item) which is already exposed/public (but a bit slower) than removeNextTick.
> I also don't like the way removeNextTick is implemented - indexOf
> means you're doing an expensive array search just to find the element
> you want to remove & removing from an array means you're shifting
> elements around which is expensive.
No, no, Look again. I'm not removing it I just modify the item to be a nop item. You can't splice the array there because if you do you won't be able to call removeNextTick from within a callback: it would break ._tickCallback.
> My preferred idea would be to either figure out some way of storing it
> in a map so that it's O(1) to insert & remove or store the index as
> part of the object you return from nextTick & then updating all the
> indexes through the array element references on removal (less ideal).
When I thought about this I decided to favour items insertion and . _tickCallback speed over that of removeNextTick, because, istm it is not something that is going to/should be done very often. But talk is cheap, show me the code :-) . If you've got a better way, sure, let's just do it better !
KTHKS for your comments.
--
Jorge.
> Oh, & just another idea - how about maintaining the setTimeout stuff
> on a separate nextTick queue that gets invoked after the ones that
> call nextTick directly - that'll maintain the current behaviour &
> pre-empt those people complaining that this somehow drastically alters
> semantics (not that I'm convinced that nextTick nor setTimeout provide
> any guarantees about the order of callbacks invoked when the timeout
> is the same).
Yep. We'd just need a separate timersQueue [] for that, and another loop just after the one that's already there in . _tickCallback. I've not done it because in my mind, still, setTimeout(,0) ought to be === nextTick... :-)
But even that wouldn't satisfy Bradley Meck :-), if, as he says, it's true that in the event loop the events queue is dispatched *after* . _tickCallback...
--
Jorge.
>
> nextTick items can be removed too with clearInterval/timeout(item) which is already exposed/public (but a bit slower) than removeNextTick.
Yup - saw that.
>
>> I also don't like the way removeNextTick is implemented - indexOf
>> means you're doing an expensive array search just to find the element
>> you want to remove & removing from an array means you're shifting
>> elements around which is expensive.
>
> No, no, Look again. I'm not removing it I just modify the item to be a nop item. You can't splice the array there because if you do you won't be able to call removeNextTick from within a callback: it would break ._tickCallback.
Good point. I need to look over the patch again, but does that mean
the array is never gc'ed?
>
>> My preferred idea would be to either figure out some way of storing it
>> in a map so that it's O(1) to insert & remove or store the index as
>> part of the object you return from nextTick & then updating all the
>> indexes through the array element references on removal (less ideal).
>
> When I thought about this I decided to favour items insertion and . _tickCallback speed over that of removeNextTick, because, istm it is not something that is going to/should be done very often. But talk is cheap, show me the code :-) . If you've got a better way, sure, let's just do it better !
You're right on this except that clearInterval will be a common use
case (typical approach is to do setInterval(f, 0) & clear it once it
is done - something to think about.
Also, I really dislike this implicit arbitrary ordering that's being
imposed on async callbacks.
> This is not
> without cost and very little gain if any.
There is significant gain - there are people trying to write code that
is common to both node & the web. Browsers don't have a concept of
nextTick, but do for setTimeout. If you can reduce & isolate the
node-isms (or remove them where unnecessary such as here), it makes it
a lot easier for them.
> Sorry - so is the current ordering nextTick, events, setTimeout(f, 0)?
That's what I understand in Bradley Mecks' message:
"I will once again point out. nextTick preempts events. setTimeout(f,0)
would preempt events always with the suggestion, this is an amazingly
large edge case for the optimization when setTimeout(f,1) would never
preempt an event."
I wanted to test it, but found out that eventEmitter.emit(event) is synchronous.
Is there a queue event ?
And if there is, shouldn't eventEmitter.emit() just push an event into that queue ?
> Also, I really dislike this implicit arbitrary ordering that's being
> imposed on async callbacks.
What do you mean ?
--
Jorge.
eventEmitter.emit should be synchronous. For example, I would expect
to call process.emit('exit') right before I call process.exit.
Similar idea for any other example. That is the typical way signals
invoke slots (typically only do deferred invocation for slots that
exist on other threads to avoid thread-safety issues).
Jorge.
> Try process.exit instead - not sure what .exit does on the command line (my try to schedule an idle event, which will never happen since there's going to always be something in the event loop).
The repl .exit is doing a self.stream.destroy(); (stream being process.stdin, istm) which will kill the repl, but not necessarily node.
Maybe there should be a .quit that called process.exit() ?
or a just process.exit() after the stream.destroy() would do ?
http://github.com/xk/node/commit/be12c250e544e99681b27bc7b8844fb3db4d4d29
--
Jorge.
Say you've got this:
var in10seconds= Date.now()+ 10e3;
while ( Date.now() < in10seconds ) ; //don't ever do this :-)
And during that 10 seconds some packets arrive, a file chunk is read, and etc ..., things that generate say 5 events while the program is in that 10 seconds loop.
1.- You don't expect these events to interrupt the loop, because they're events, not interrupts.
2.- You'd expect them to be handled in the order that they happened. For that there's an -fifo- event queue, right ?
Now, say that the line right after that loop were:
process.emit("someEvent");
Why would you expect that "someEvent" event to be handled *before* the ones that were already pending ?
I'd say you should not expect that to be so.
Which is no to say that sometimes you might want an event to be handled synchronously, but then it's not really behaving as an "event", but more like an interrupt.
Don't you think so ?
--
Jorge.
> clearNextTick is a good name.
[x] Done
http://github.com/xk/node/commit/df1de048e4c7de861bcb38c6520462a75ab356ab
> I don't have an opinion on whether to expose it or not. Ask Ryan.
Yep. Let's see what says the boss.
--
Jorge.
when talking about preemption, nextTick occurs before queued events
(all of them). and setTimeout occurs after queued events. That is a
rather large difference.
--
You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
Sure, that's how it works now, but the important question is whether this is a feature or just an API leak? After all this is an event queue -- should you ever depend on a specific order of operations?
--
You received this message because you are subscribed to the Google Groups "nodejs" group.
To post to this group, send email to nod...@googlegroups.com.
To unsubscribe from this group, send email to nodejs+un...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/nodejs?hl=en.
Sure, that's how it works now, but the important question is whether this is a feature or just an API leak? After all this is an event queue -- should you ever depend on a specific order of operations?
Yes, but only with semantically related events. Like chunks of data coming off of a socket. These have to be in order. There may be other events firing that are interspersed with those data events. That's fine and shouldn't be a problem. But the ordering if events is significant. The word "event" doesn't immediately presume randomness. It just means asynchronous right?.
> 2.- You'd expect them to be handled in the order that they happened. For that there's an -fifo- event queue, right ?
Right
> Now, say that the line right after that loop were:
>
> process.emit("someEvent");
>
> Why would you expect that "someEvent" event to be handled *before* the ones that were already pending ?
Because you're not emitting an event so much as a signal. Maybe it might be helpful to have a send('signal') that posts it on the event queue.
> I'd say you should not expect that to be so.
>
> Which is no to say that sometimes you might want an event to be handled synchronously, but then it's not really behaving as an "event", but more like an interrupt.
JS has no concept of interrupts - not sure what you're trying to say.
>
> Don't you think so ?
I disagree on this point.
Since JS will remain single-threaded for the foreseeable future, I
don't see how that could change. There'll always be an order of
execution for event/timer queues, and the way it is now makes perfect
sense, IMO. You shouldn't expect a timer to fire before an event for
any reasonable logic, but the opposite is true for nextTick since it's
supposed to run 'as soon as possible' - it implies awareness of an
event loop, which setTimeout doesn't.
A timeout of 0 implies 0 delay to me. Yet you are making assumptions that there is still just a little bit of extra delay imposed so that there's some kind of implicit ordering from the by-product of the implementation.
I don't mind making setTimeout faster. But doing so involves injecting it into the event loop in the same way nextTicks are. But setTimeouts can be cancelled as well. Well if we're allowing that, should we do it for nextTick too? The answer is no, IMO.
But now we have to talk endlessly about what it means that removable setTimeout events are dispersed throughout the event queue instead of being handled afterwards.
What the intended behavior should be is not clear. This is a strong indication to me that is a bad idea. If we do it, then the semantics it creates will make setTimeout(f, 0) act differently in node then it does in the browser. This is another red flag for me.
2) Semantic compatibility with the browser - I believe this change goes against the goal of browser compatibility. setTimeout in the browser is always delayed. So you're proposing a solution that would explicitly make it work differently.
--
*K*Hz : 400.000 timers/second.
--
Jorge.
--