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);
}

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 <[email protected]> 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 <[email protected]> wrote:
> > > On Fri, Jun 8, 2012 at 7:23 PM, Jimb Esser <[email protected]> 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 <[email protected]> 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 <[email protected]> 
> > > > > 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 <[email protected]> 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 
> > > > > > > <[email protected]>wrote:
>
> > > > > > > > No need to change the API, we have .bind() - use the language
> > > > > > > > features, don't reinvent them.
>
> > > > > > > > 2012/6/8 Tim Caswell <[email protected]>:
>
> > > > > > > > > On Fri, Jun 8, 2012 at 2:10 PM, tjholowaychuk <
> > > > > > > > [email protected]>
> > > > > > > > > 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.
>
> > > > > > > > (Insert
> > > > > > > > > statement about performance only mattering if it's 
> > > > > > > > > significant...)
>
> > > > > > > > > I usually will bind all my methods from the prototype that 
> > > > > > > > > will be
> > > > > > > > used as
> > > > > > > > > callbacks to the instance itself inside the constructor.  
> > > > > > > > > This gives
>
> > > > > > > > me a
> > > > > > > > > ton more "own" properties, but otherwise is fairly elegant.
>
> > > > > > > > > > On Jun 8, 11:52 am, AJ ONeal <[email protected]> wrote:
> > > > > > > > > > >     emitter.on('data', myModule.dataHandler, myModule);
>
> > > > > > > > > > > Even if myModule were to subclass EventEmitter, wouldn't 
> > > > > > > > > > > I still
> > > > > > > > need to
> > > > > > > > > > > pass in the `myModule` instance so that I get the correct 
> > > > > > > > > > > `this`?
>
> > > > > > > > I
> > > > > > > > > > > don't
> > > > > > > > > > > think I understood what you meant by that.
>
> > > > > > > > > > > And then these cases as well:
>
> > > > > > > > > > >     fs.readFile(file, encoding, myModule.fileHandler, 
> > > > > > > > > > > myModule);
>
> > > > > > > > > > >     process.nextTick(myModule.tickHandler, myModule);
>
> > > > > > > > > > > The list goes on. Obviously not a small project. Not 
> > > > > > > > > > > difficult
> > > > > > > > either,
> > > > > > > > > > > just
> > > > > > > > > > > tedious.
>
> > > > > > > > > > > AJ ONeal
>
> > > > > > > > > > > On Fri, Jun 8, 2012 at 12:42 PM, Tim Caswell 
> > > > > > > > > > > <[email protected]
>
> > > > > > > > > > > wrote:
> > > > > > > > > > > > Actually event emitters already call in the scope of the
>
> > > > > > > > emitter, so
> > > > > > > > > > > > there
> > > > > > > > > > > > is no need for a specific "this" value there.  Just 
> > > > > > > > > > > > subclass
> > > > > > > > > > > > EventEmitter
> > > > > > > > > > > > and use normal methods.
>
> > > > > > > > > > > > On Fri, Jun 8, 2012 at 1:34 PM, AJ ONeal 
> > > > > > > > > > > > <[email protected]>
> > > > > > > > wrote:
>
> > > > > > > > > > > > > If you're going to use `this` then you must have a 
> > > > > > > > > > > > > callback.
> > > > > > > > It would
> > > > > > > > > > > > > make no sense to have a `this` and nothing to apply 
> > > > > > > > > > > > > it to.
>
> > > > > > > > > > > > > You think EventEmitters would feel the overhead of 
> > > > > > > > > > > > > the if?
>
> > > > > > > > > > > > >     // context is Array, Object, or Function.
> > > > > > > > > > > > >     // Numbers, Strings, and Booleans need not 
> > > > > > > > > > > > > `apply` (very
>
> > > > > > > > punny)
> > > > > > > > > > > > >     if (context) {
> > > > > > > > > > > > >       fn.call(context, a, b, c);
> > > > > > > > > > > > >     } else {
> > > > > > > > > > > > >       fn(a, b, c);
> > > > > > > > > > > > >     }
>
> > > > > > > > > > > > > As far as the guesswork, well, I hear you on that. 
> > > > > > > > > > > > > I've
> > > > > > > > already done
> > > > > > > > > > > > > my
> > > > > > > > > > > > > ranting at UtahJS Conf. Put this as one more in the 
> > > > > > > > > > > > > bucket of
>
> > > > > > > > reasons
> > > > > > > > > > > > > that
>
> ...
>
> read more »

-- 
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 [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/nodejs?hl=en?hl=en

Reply via email to