-
-
Save jed/449728 to your computer and use it in GitHub Desktop.
var puts = require( "sys" ).puts | |
, contextFn = function( a ){ return a && this() } | |
, argFn = function( a, b ){ return b && a() } | |
, time; | |
time = +new Date; | |
for ( var i = 0; i < 10e6; i++ ) contextFn.call( contextFn, contextFn ); | |
puts( "as context: " + ( +new Date - time ) ); | |
time = +new Date; | |
for ( var i = 0; i < 10e6; i++ ) argFn( argFn, argFn ); | |
puts( "as argument: " + ( +new Date - time ) ); |
No, you need to access the passed parameter / this. Otherwise the compiler might optimize things in a way that will mess with the results.
okay, i'm accessing the arguments now, results on my machine are like this:
as context: 581
as argument: 314
what do you think?
well, I'm not surprised argument passing is faster : ), but your test should be more fair now.
But I'm actually confused, shouldn't your test functions call themselves endlessly / recursively?
i don't think so, because they get short-circuited without the non-callback arg.
is a .000025ms hit per function worth it?
Ah, right, on the first recursive call the functions return false, that explains it.
If it's worth it: How many fab functions are called per request? Is it just the ones on the matching path, or will all functions get called every time?
If it's just the hot path I doubt call will make a difference. However, are you just using 'call', or are you also using 'apply'? That could be an entirely different story
well, just the hot path. so if you have a bunch of chained ternary path apps, for example, all apps until the path is matched.
but yeah, the more binary your tree the fewer the apps, so i'd imagine it'd grow near O(log n) for a fairly balanced site.
is it true that call
and apply
have different performance? i don't think i'd be using apply
, because each app only allows a single argument (the data payload). any use of apply would only pass the existing arguments object too, not an array or anything.
i'm leaning towards keeping this
as the universal callback pattern, because:
- it's one less thing i have to worry about naming for
- it's more naturally omittable:
app.call(cb,data)
andapp(data)
vs.app(data,cb)
andapp(undefined,cb)
- it keeps the functions "airtight", since all possible ways to pass data would be used
- it avoids ambiguity: with
app(data,cb)
, if data isundefined
, i can't determine whetherundefined
was actually intended to be passed, or if data is supposed to be blank. withapp.call(cb,data)
, i can look at arguments.length to disambiguate.
thoughts?
apply
is different because it can pass a variable number of arguments which is harder to optimize for V8. I have not benchmarked it, but I suspect it to be substantially slower than just call
.
I think you should go ahead with 'this'. Everything else seems like pre-mature optimization at this point. I suspect other parts of fab to be substantially slower, so you shouldn't worry about this one for now : ).
thanks, felix. your feedback is very much appreciated!
あなたは歓迎されて
results are usually like this for me:
is this a valid way of testing the overhead of setting a context for a function call?