This is an example of *very* productive feedback :) Tim Caswell Rules!
On May 29, 2012, at May 29, 20123:10 PM, Tim Caswell wrote: > For the record, I know I have code that will break under this change, but I > didn't bother linking to it because it's so trivial for me to fix. I do, > however have code that is broken under the current implementation that I > can't fix. > > On Tue, May 29, 2012 at 5:05 PM, Mikeal Rogers <mikeal.rog...@gmail.com> > wrote: > > > > > On May 29, 2012, at May 29, 20122:42 PM, Marco Rogers wrote: > >> Mikeal, I understand your frustration, but that's not how I read the >> history. nextTick was *intended* for this use case. But it sounds like it >> was the wrong solution. nextTick was implemented as "yield to the event loop >> for whatever else may happen". It's always been pretty clear to me that some >> early data events may get through this gap. The fact that you didn't >> actually want this doesn't mean there's a bug in nextTick. It means you >> screwed up. It means there's a bug in node because you took a valid nextTick >> implementation and used it for the wrong thing. It means you need another >> solution to solve your original problem. I thought that's why we started >> talking about setImmediate. > > The problem with this characterization of the API's history is that it's > actually not distinguishable from setTimeout(fn, 0) except in implementation. > As described, they are for quite literally the same thing although one of > them is a little better at it because of an implementation detail. If this > characterization is true (i don't believe it is) then we should re-purpose or > remove nextTick() and improve the performance of setTimeout(fn,0). I'm not > suggesting that is what we do, but it's the logical conclusion to this > characterization. > >> >> As for whether it's valid to use nextTick or setTimeout or whatever to break >> up computation, that's not your call. > > Are you saying that core can't state the intention of an API? That's insane. > > Core is free to change the implementation details and semantics of an API at > any time, and has on many occasions. This is always done with the intention > of making it *better*. In order to characterize what is "better" the API must > have a purpose and that has always been dictated by core (Ryan and then > Isaac). > >> People have been doing this in javascript for ages. Node can provide a >> "better" solution, but crippling current valid solutions is not really >> acceptable for a platform that claims to want to be simple and consistent >> and just javascript. IMO, cluster/child_process is for scaling request >> throughput for servers. It has little to do with breaking up computation >> though it can be used for that. This is not my impression, but one I got >> from you and Isaac and other node people when it was being designed. It >> feels like what's happening now, is that you're changing that tune so you >> can push this change forward. But whatever. >> >> You know if you're going to get upset when you receive honest, constructive >> feedback that you requested from actual users of your software, you should >> probably consider just not asking. > > This is what happened. > > Isaac said "this change makes sense, does anyone have code that will break". > To date, *nobody* has shown real world code that will break or linked to any > projects that will break. We *know* of code that breaks in production under > load due to the current semantics, that's why the change was proposed in the > first place. > > Instead, we got a lot of comments about names and about theoretical breakage > in code without anyone noting running code that actually breaks or is even > valid. And now we're being taken down the rabbit hole of "I can't use this > for something it wasn't designed for". > > The way in which people are providing feedback to this proposed changed is > unproductive because they do not recognize the reality of the current > semantics. > 1) that we cannot remove nextTick() and it is heavily relied on. > 2) that much of the code that *currently* relies on nextTick() breaks under > heavy load because of the current implementation. > > All of this feedback is "me too". It's statements of opinion without > reference the problem that must be solved. > > The intention of feedback should be to change the minds of those that > proposed the change, not to prove that your'e right under your terms. > > If it seems as though the responses from Isaac are callus it is because it is > not his job to convince you that this is a real problem, it's your job to > convince him that your solution benefits everyone better and still solves the > problem at hand. That is not happening. > >> >> :Marco >> >> On Tuesday, May 29, 2012 2:18:35 PM UTC-7, Mikeal Rogers wrote: >> The job of core is to provide the best API possible to accomplish several >> use cases. >> >> When core provides an API to handle that use case and people decide to >> ignore it, do something inferior with an API that was not designed for that >> use case, and then protest altering the this API to better match the use >> case it was actually intended for I don't have the words to describe how >> frustrating it is. >> >> This is not a matter of "opinion". These APIs were created and documented >> for a *purpose*. It's great when people find more than one purpose for a >> given API but when their use case is actually covered by another interface >> that was specifically designed to handle it we have to ignore that input on >> the other API. >> >> The "change" we're talking about makes nextTick() behave the way most people >> presume it works and for the use case it was designed for (adding handlers >> after the current stack is complete but before IO gets processes) the >> current behavior is a bug. The suggestion that we should let it remain >> because the current behavior (which is broken for the desired use case) >> fills another one it was not designed for and for which we have other >> specifically designed API is ludicrous. >> >> -Mikeal >> >> On May 29, 2012, at May 29, 20122:08 PM, Marco Rogers wrote: >> >>> Translation: "You're doing something reasonable. But we don't think you >>> should do it that way, so we're going to shoot you in the foot and then >>> blame you for it." I'm on board with this plan. <- sarcasm >>> >>> Seriously though. Can we at least hear what other options y'all have >>> considered for fixing the original problem? Is there a test case that >>> reproduces it that we can examine? I don't want to mess with nextTick >>> because it works as designed. But if there's no other solution to the >>> problem, I could get behind introducing setImmediate. But with that it >>> seems we're signing up for a whole new round of educating devs about what >>> to do in order to not miss their data events. Sure it seems easy in theory >>> (change nextTick to setImmediate), but in practice it will create a lot of >>> confusion and ambiguity about what just changed. >>> >>> :Marco >>> >>> PS - Sorry I missed the message about moving discussion to the github >>> ticket :-/ >>> >>> >>> On Tue, May 29, 2012 at 1:45 PM, Isaac Schlueter <i...@izs.me> wrote: >>> Computationally expensive stuff should be done in a child process, or >>> a uv_work_t thread in an addon. nextTick is a bad fit for this. >>> setTimeout(fn, 0) is not quite as bad, but it is slower. >>> >>> We can look into adding a setImmediate function for 0.9 that matches >>> the semantics of the web browser. The intent of setImmediate is to be >>> used for cases like this, and it should be pretty easy to implement. >>> >>> On Tue, May 29, 2012 at 1:31 PM, Mikeal Rogers <mikeal.rog...@gmail.com> >>> wrote: >>> > I have never seen nextTick recommended for breaking up computationally >>> > expensive tasks, this is what cluster and child_process are for. >>> > >>> > Also, setTimeout(cb,0) is very efficient in node and does not suffer the >>> > penalties we are familiar with from the browser. It's actually a better >>> > fit >>> > for this use case than nextTick(). >>> > >>> > -Mikeal >>> > >>> > >>> > On May 29, 2012, at May 29, 201212:23 PM, Bruno Jouhier wrote: >>> > >>> > +1 >>> > >>> > nextTick is the efficient way to yield to another "thread of processing" >>> > (thread between quotes of course) when performing an expensive >>> > computation. >>> > So it is the antidote to starvation and thus a very useful call. >>> > >>> > If you change its behavior, you should at least provide a replacement call >>> > which will be at least as efficient (unlike setTimeout(cb, 0)). And then >>> > why >>> > not keep nextTick as is and introduce another call with a different name >>> > (like afterTick as someone suggested) if you really need one. >>> > >>> > >>> > On Tuesday, May 29, 2012 2:43:20 AM UTC+2, phidelta wrote: >>> >> >>> >> I think that the current semantics have value. I use nextTick when I >>> >> want to ensure that io can happen between the invocation and the >>> >> ticked call. As well as to work with a new call stack. >>> >> >>> >> For example when I emit an event whose lister also emits an event and >>> >> so on, I create a potentially long chain of stuff that can happen >>> >> within a tick. So when I emit from within a listener I usually >>> >> nextTick the emit to allow io in between. >>> >> >>> >> So if you change nextTick to really mean "at the end of this tick", at >>> >> least we will want a function like reallyNextTick that keeps the >>> >> current behavior. Of course I would need to do a search replace over a >>> >> lot of code, but I could live with that. >>> >> >>> >> >>> >> On May 26, 7:50 pm, Isaac Schlueter <i...@izs.me> wrote: >>> >> > How would you feel about changing the semantics of process.nextTick >>> >> > such that the nextTick queue is *always* cleared after every v8 >>> >> > invocation, guaranteeing that a nextTick occurs before any IO can >>> >> > happen? >>> >> > >>> >> > This would imply that you can starve the event loop by doing nextTick. >>> >> > So, for example, the timeout would never fire in this code: >>> >> > >>> >> > setTimeout(function () { >>> >> > console.log('timeout')}) >>> >> > >>> >> > process.nextTick(function f () { >>> >> > process.nextTick(f) >>> >> > >>> >> > }) >>> >> > >>> >> > Reasoning: >>> >> > >>> >> > We have some cases in node where we use a nextTick to give the user a >>> >> > chance to add event handlers before taking some action. However, >>> >> > because we do not execute nextTick immediately (since that would >>> >> > starve the event loop) you have very rare situations where IO can >>> >> > happen in that window. >>> >> > >>> >> > Also, the steps that we go through to prevent nextTick starvation, and >>> >> > yet try to always have nextTick be as fast as possible, results in >>> >> > unnecessarily convoluted logic. >>> >> > >>> >> > This isn't going to change for v0.8, but if no one has a use-case >>> >> > where it's known to break, we can try it early in v0.9. >>> > >>> > >>> >>> >>> >>> -- >>> Marco Rogers >>> marco.rog...@gmail.com | https://twitter.com/polotek >>> >>> Life is ten percent what happens to you and ninety percent how you respond >>> to it. >>> - Lou Holtz >> > >