Re: [nodejs] Re: .bind performance (Was Re: context (thisness) to EventEmitter#on, process.nextTick, etc)
On Friday, June 8, 2012 at 8:29 PM, Jimb Esser wrote: > Binding more than once is very common > > The bound function returned by fn.bind cannot be rebound and will silently ignore any attempts to do so. > - any code that is written with > a closure instead can be written with a static function and a .bind > (and, in general, be more efficient, causing less heap pressure). > > I think you might be misusing terminology. Perhaps you could share a code example that illustrates your claim? Rick > > But, yeah, the immediate bind vs call was just in response to AJs > query, and it's pretty clear there's no reason to do that > (unless .bind was magically efficient, which it's not, it's just > generally more efficient than a new closure). > > > > On Jun 8, 5:22 pm, Rick Waldron wrote: > > On Fri, Jun 8, 2012 at 7:23 PM, Jimb Esser wrote: > > > [Moved to nodejs instead of nodejs-dev since this is of general interest > > > and only tangental to the original request] > > > > > > > > > > I've never thought of using .bind instead of .call, but since .bind does > > > allocate something, and .call theoretically doesn't have to, I'd just > > > assume .call is more efficient, though I've learned any performance > > > assumptions about JS are usually incorrect ^_^. > > > > > > > > > > Doing a quick jsperf test of the things discussed here: > > > http://jsperf.com/bind-vs-call2 > > > Results are... questionable, and I don't put too much stock in micro-tests > > > like this, as the optimizer is good at making them go fast in inconsistent > > > ways. But, anyway, f.call(o) is way faster than f.bind(o)(), which is not > > > surprising. Slightly surprising, .bind seems to underperform closures > > > significantly in this case, though (at least on the older version of V8 > > > node is using), in real-world apps (at least, ours), I'm pretty certain > > > .bind is generally better... also allocates less memory (although in a > > > micro-test like this V8 likely effectively optimizes out any memory > > > allocations from the no-op closures). > > > > > > > > > This comparison is unbalanced -- when would you ever bind() more then once? > > The bound function cannot be rebound. Furthermore, when would you ever > > bind() and immediately execute? Never - because the correct approach is to > > use call() when immediate invocation is required. bind() is one shot deal > > that returns a new bound function to be called later. > > > > Rick > > > > > > > > > > > > > > > > > > > > > - Jimb Esser > > > > > On Fri, Jun 8, 2012 at 3:14 PM, AJ ONeal wrote: > > > > > > Interesting. So have you found bind() to be more or less efficient than > > > > .call() and or .apply()? > > > > > > > > > > > > > > > AJ ONeal > > > > > > On Fri, Jun 8, 2012 at 3:48 PM, Jimb Esser wrote: > > > > > > > Technically, at least in V8, .bind is a lot lighter weight than an > > > > > anonymous function. There are a large number of micro-benchmarks to > > > > > look > > > > > at on jsperf.com, but for an actual anecdote, at one point we > > > > > accidentally required in a module which overrode > > > > > Function.prototype.bind > > > > > with something that created an anonymous function (some > > > > > browser-support > > > > > code for pre-.bind browsers), and our performance tanked, garbage > > > > > collection times increased significantly. > > > > > > > > > > > > > > > > > > > > > On Fri, Jun 8, 2012 at 2:25 PM, AJ ONeal wrote: > > > > > > > > If I'm not mistaken, bind() has the same technical drawbacks as > > > > > > using > > > > > > an anonymous function (higher memory usage, more garbage > > > > > > collection, and > > > > > > slower says Tim), but it does solve the maintainability / > > > > > > prettiness issue. > > > > > > > > > > > > > > > > > > > > > > > > > > > > I just want to point out that Raspberry Pi is now shipping. > > > > > > NodeJS is a very attractive option for development. > > > > > > > > > > > > > > > > > > > > > > > > > > > > My own experience with my ARM-based media server has lead me to be a > > > > > > believer in prototypes and leaner code. I can't say that one little > > > > > > anony > > > > > > here and there is going to blow up an application, but I know for a > > > > > > fact > > > > > > that there are significant performance gains when they are avoided. > > > > > > > > > > > > > > > > > > > > > > > > > > > > I know it doesn't seem like a big deal now. But one day you may > > > > > > change > > > > > > your mind. > > > > > > > > > > > > > > > > > > > > > > > > > > > > AJ ONeal > > > > > > > > On Fri, Jun 8, 2012 at 2:22 PM, George Stagas > > > > > > wrote: > > > > > > > > > No need to change the API, we have .bind() - use the language > > > > > > > features, don't reinvent them. > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > 2012/6/8 Tim Caswell : > > > > > > > > > > On Fri, Jun 8, 2012 at 2:10 PM, tjhol
Re: [nodejs] Re: .bind performance (Was Re: context (thisness) to EventEmitter#on, process.nextTick, etc)
FWIW, my experience with .bind on V8 has always been that it's actually significantly slower than just creating a closure yourself. For a microbenchmark, see http://jsperf.com/bind-vs-closure Besides the memory overhead of using bind vs calling with call, bind has strange semantics. For example, many developers don't know that you can't rebind a function. It's rather opaque and weird. I don't *like* working with bound functions. I do it many times anyway because the syntax is rather pretty and the performance of that part isn't critical. On Fri, Jun 8, 2012 at 7:34 PM, Rick Waldron wrote: > > On Friday, June 8, 2012 at 8:29 PM, Jimb Esser wrote: > > Binding more than once is very common > > The bound function returned by fn.bind cannot be rebound and will silently > ignore any attempts to do so. > > > > - any code that is written with > a closure instead can be written with a static function and a .bind > (and, in general, be more efficient, causing less heap pressure). > > I think you might be misusing terminology. Perhaps you could share a code > example that illustrates your claim? > > Rick > > > > But, yeah, the immediate bind vs call was just in response to AJs > query, and it's pretty clear there's no reason to do that > (unless .bind was magically efficient, which it's not, it's just > generally more efficient than a new closure). > > > > On Jun 8, 5:22 pm, Rick Waldron wrote: > > On Fri, Jun 8, 2012 at 7:23 PM, Jimb Esser wrote: > > [Moved to nodejs instead of nodejs-dev since this is of general interest > and only tangental to the original request] > > > I've never thought of using .bind instead of .call, but since .bind does > allocate something, and .call theoretically doesn't have to, I'd just > assume .call is more efficient, though I've learned any performance > assumptions about JS are usually incorrect ^_^. > > > Doing a quick jsperf test of the things discussed here: > http://jsperf.com/bind-vs-call2 > Results are... questionable, and I don't put too much stock in micro-tests > like this, as the optimizer is good at making them go fast in inconsistent > ways. But, anyway, f.call(o) is way faster than f.bind(o)(), which is not > surprising. Slightly surprising, .bind seems to underperform closures > significantly in this case, though (at least on the older version of V8 > node is using), in real-world apps (at least, ours), I'm pretty certain > .bind is generally better... also allocates less memory (although in a > micro-test like this V8 likely effectively optimizes out any memory > allocations from the no-op closures). > > > This comparison is unbalanced -- when would you ever bind() more then once? > The bound function cannot be rebound. Furthermore, when would you ever > bind() and immediately execute? Never - because the correct approach is to > use call() when immediate invocation is required. bind() is one shot deal > that returns a new bound function to be called later. > > Rick > > > > > > > > > > - Jimb Esser > > > On Fri, Jun 8, 2012 at 3:14 PM, AJ ONeal wrote: > > > Interesting. So have you found bind() to be more or less efficient than > .call() and or .apply()? > > > AJ ONeal > > > On Fri, Jun 8, 2012 at 3:48 PM, Jimb Esser wrote: > > > Technically, at least in V8, .bind is a lot lighter weight than an > anonymous function. There are a large number of micro-benchmarks to look > at on jsperf.com, but for an actual anecdote, at one point we > accidentally required in a module which overrode Function.prototype.bind > with something that created an anonymous function (some browser-support > code for pre-.bind browsers), and our performance tanked, garbage > collection times increased significantly. > > > On Fri, Jun 8, 2012 at 2:25 PM, AJ ONeal wrote: > > > If I'm not mistaken, bind() has the same technical drawbacks as using > an anonymous function (higher memory usage, more garbage collection, and > slower says Tim), but it does solve the maintainability / prettiness issue. > > > I just want to point out that Raspberry Pi is now shipping. > NodeJS is a very attractive option for development. > > > My own experience with my ARM-based media server has lead me to be a > believer in prototypes and leaner code. I can't say that one little anony > here and there is going to blow up an application, but I know for a fact > that there are significant performance gains when they are avoided. > > > I know it doesn't seem like a big deal now. But one day you may change > your mind. > > > AJ ONeal > > > On Fri, Jun 8, 2012 at 2:22 PM, George Stagas wrote: > > > No need to change the API, we have .bind() - use the language > features, don't reinvent them. > > > 2012/6/8 Tim Caswell : > > > On Fri, Jun 8, 2012 at 2:10 PM, tjholowaychuk < > > tjholoway...@gmail.com> > > wrote: > > > what's wrong with .bind() ? > > > Mainly the overhead. Bind creates a new function every time it's > > called, > > and calling the bound function is a bit slower, especially in V8. > > (Ins
Re: [nodejs] Re: .bind performance (Was Re: context (thisness) to EventEmitter#on, process.nextTick, etc)
On Saturday, June 9, 2012 at 12:21 AM, Jimb Esser wrote: > By "binding more than once", I mean binding the same original function > multiple times (with different parameters), not binding the result of > a previously bound function. > > An example of using bind instead of a closure: > original: > function backupFile(filename, cb) { > fs.unlink(filename + '.bak', function(err) { > fs.rename(filename, filename + '.bak', cb); > }); > } > Using bind and no run-time function creation: > function backupFile(filename, cb) { > fs.unlink(filename + '.bak', step2.bind(undefined, filename, cb)); > } > function step2(filename, cb, err) { > fs.rename(filename, filename + '.bak', cb); > } > I would agree that a function expression makes more sense in this case -- there is actually no reason to use bind() here at all. In fact, the comparison still doesn't balance because you're forcing bind() into a role that doesn't make sense. Additionally, this example is wantonly adding a function to the stack. bind()'s primary use case is passing one function's scope to another or "sharing" a "scope" (represented by an object) between with an unrelated functions. Rick > > Doing some microbenchmarks, it does seem, however, that the .bind > version is allocating more memory (only using a little more on older > V8 versions, but seems to be using over triple the amount of the > closure on the V8 version in node 0.6.18), so I retract my earlier > statement about bind generally being better performing. I was > confusing the results of my anecdotal evidence, which was that > implementing your own .bind function (or accidentally including a > library that overrides Function.prototype.bind) is notably slower, but > V8 seems good at optimizing closures in a local scope. > > In theory the closure can also grab references to local variables in > the scope, causing them not to get garbage collected as quickly, but > in practice V8 seems to not grab references to the entire scope, just > the appropriate objects. > > On Jun 8, 5:34 pm, Rick Waldron wrote: > > On Friday, June 8, 2012 at 8:29 PM, Jimb Esser wrote: > > > Binding more than once is very common > > > > > > The bound function returned by fn.bind cannot be rebound and will silently > > ignore any attempts to do so. > > > > > - any code that is written with > > > a closure instead can be written with a static function and a .bind > > > (and, in general, be more efficient, causing less heap pressure). > > > > > > > > > I think you might be misusing terminology. Perhaps you could share a code > > example that illustrates your claim? > > > > Rick > > > > > > > > > > > > > > > > > > > > > But, yeah, the immediate bind vs call was just in response to AJs > > > query, and it's pretty clear there's no reason to do that > > > (unless .bind was magically efficient, which it's not, it's just > > > generally more efficient than a new closure). > > > > > > > > > > On Jun 8, 5:22 pm, Rick Waldron wrote: > > > > On Fri, Jun 8, 2012 at 7:23 PM, Jimb Esser wrote: > > > > > [Moved to nodejs instead of nodejs-dev since this is of general > > > > > interest > > > > > and only tangental to the original request] > > > > > > > > > > > > > > > > > > > > > > > > > > > > I've never thought of using .bind instead of .call, but since .bind > > > > > does > > > > > allocate something, and .call theoretically doesn't have to, I'd just > > > > > assume .call is more efficient, though I've learned any performance > > > > > assumptions about JS are usually incorrect ^_^. > > > > > > > > > > > > > > > > > > > > > Doing a quick jsperf test of the things discussed here: > > > > > http://jsperf.com/bind-vs-call2 > > > > > Results are... questionable, and I don't put too much stock in > > > > > micro-tests > > > > > like this, as the optimizer is good at making them go fast in > > > > > inconsistent > > > > > ways. But, anyway, f.call(o) is way faster than f.bind(o)(), which > > > > > is not > > > > > surprising. Slightly surprising, .bind seems to underperform closures > > > > > significantly in this case, though (at least on the older version of > > > > > V8 > > > > > node is using), in real-world apps (at least, ours), I'm pretty > > > > > certain > > > > > .bind is generally better... also allocates less memory (although in a > > > > > micro-test like this V8 likely effectively optimizes out any memory > > > > > allocations from the no-op closures). > > > > > > > > > > > > > > > > > > > > This comparison is unbalanced -- when would you ever bind() more then > > > > once? > > > > The bound function cannot be rebound. Furthermore, when would you ever > > > > bind() and immediately execute? Never - because the correct approach is > > > > to > > > > use call() when immediate invocation is required. bind() is one shot > > > > deal > > > > that returns a new bound function to be called later. > > > > > > > > >
Re: [nodejs] Re: .bind performance (Was Re: context (thisness) to EventEmitter#on, process.nextTick, etc)
> > snip > > [1] https://gist.github.com/2899468 > > Nothing about the code in this gist actually needs to use bind(), but your findings are certainly as expected - bind() actually creates a whole new function object to return, whereas closing over with a function expression or passing as arguments clearly do not. Just a heads up, there is quite a bit of stack and invocation noise being created in this example - a quick way to see this is by removing cb() and cb.call(), you'll notice the values lower. Rick -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to nodejs@googlegroups.com To unsubscribe from this group, send email to nodejs+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en
Re: [nodejs] Re: .bind performance (Was Re: context (thisness) to EventEmitter#on, process.nextTick, etc)
On 6/9/12 2:11 AM, Brandon Benvie wrote: Part of the slowdown is because builtin bind has to handle construct as well. But yeah, V8's bind is *notably* slow when you do a comparison of either a full manual implementation of bind semantics yourself, or compared to say Spidermonkey. I'm not sure what the deal is there, but it *is* a V8 issue in some way or another. For reference, this is the V8 bind code: https://github.com/joyent/node/blob/master/deps/v8/src/v8natives.js#L1578 I was just reading up on `bind` versus closure performance. More discussion on all that `bind` does that a closure doesn't do here: http://stackoverflow.com/questions/8656106/why-is-function-prototype-bind-slow -- Alan - @bigeasy -- Job Board: http://jobs.nodejs.org/ Posting guidelines: https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines You received this message because you are subscribed to the Google Groups "nodejs" group. To post to this group, send email to nodejs@googlegroups.com To unsubscribe from this group, send email to nodejs+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/nodejs?hl=en?hl=en