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
>> 
> 
> 

Reply via email to