| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
There was a problem hiding this comment.
fyi this is unnecessary, just use arguments in the fn.apply()
Sorry, something went wrong.
There was a problem hiding this comment.
It looks correct to me. It needs to slice off the fn argument, doesn't it?
Sorry, something went wrong.
There was a problem hiding this comment.
@rvagg, what @bnoordhuis says is correct, the function needs all the arguments but the first, which is the function itself.
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry, didn't notice the 1
Sorry, something went wrong.
There was a problem hiding this comment.
Shouldn't it be the same as https://github.com/iojs/io.js/blob/v0.12/lib/events.js#L103 ?
Sorry, something went wrong.
|
LGTM FWIW. |
Sorry, something went wrong.
|
I suppose one question that needs answering is whether domain.run() is performance-sensitive enough that adding a slice+apply introduces noticeable overhead. I'm guessing the answer is 'no' but I don't use domains enough to really know for sure. Opinions? @micnic Can you make the commit log conform to the template as described in CONTRIBUTING.md? Thanks. |
Sorry, something went wrong.
|
@bnoordhuis I agree. Also it's possible just to call enter() and exit() manually |
Sorry, something went wrong.
|
@bnoordhuis, I'll add a switch for different cases as @vkurchatkin proposes. related to the commit log, should I make a new pull request or just another commit with a more verbose description? (it's my first PR) |
Sorry, something went wrong.
|
@micnic That's a good idea but can you then also add a small benchmark in benchmarks/ that shows that the switch statement actually speeds things up? Thanks. As to the commit log, you can just git commit --amend it and and force-push it to your feature branch (or git rebase -i it when you add that benchmark.) |
Sorry, something went wrong.
|
@bnoordhuis, I added the benchmark and made some changes to the arguments slicing logic to: if (arguments.length >= 2) {
args = Array.prototype.slice.call(arguments, 1);
ret = fn.apply(this, args);
} else {
ret = fn.call(this);
}it's similar to what is used in setInterval() or setTimeout, from the benchmark I did not observe any performance impact. Now, what I discovered is that we also should bind the arguments to the domain if they may emit any errors, take in count this use case: var domain = require('domain');
var events = require('events');
var dom = domain.create();
var emitter = new events.EventEmitter();
dom.on('error', function (error) {
console.log(error.message + ' is caught');
});
dom.run(function (ee) {
ee.emit('someEvent');
}, emitter);
// This error is not caught by the domain
emitter.emit('error', new Error('Oh No!'));What do you think about explicitly binding the arguments to the domain? |
Sorry, something went wrong.
sounds counterintuitive and probably will cause lots of confusion |
Sorry, something went wrong.
|
Hello! I am pleased to see your valuable contribution to this project. Would you Questions:
Please provide the answers in an ordered list like this:
Note that I am just a bot with a limited human-reply parsing abilities, In case of success I will say: ...summoning the core team devs!. In case of validation problem I will say: Sorry, but something is not right here:. Truly yours, Responsibilities
|
Sorry, something went wrong.
|
Sorry, something went wrong.
|
...summoning the core team devs! |
Sorry, something went wrong.
|
I think this conflicts with #66. I'll bring it up in the TC meeting today; if we are going to deprecate domains, it doesn't make sense to extend the API. |
Sorry, something went wrong.
There was a problem hiding this comment.
I did some quick research and calling Array.prototype.slice.call(arguments) always deopts the function. You can see it for yourself when you run with --trace_opt --trace_deopt; V8 always bails out with "Bad value context for arguments value". It's unavoidable and probably doesn't matter much in the grand scheme of things but it's still a pity.
Sorry, something went wrong.
There was a problem hiding this comment.
I believe you can work around this by copying arguments to args using a loop. Not sure if it's worth it in this case.
Ref: https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#32-leaking-arguments
Sorry, something went wrong.
There was a problem hiding this comment.
Sorry, something went wrong.
There was a problem hiding this comment.
This is a bit of a fun one because slicing the arguments manually is not usually faster than calling Array::slice() - so whether this is worthwhile or not depends on how much work the rest of your function does. In this case that function isn't doing a lot of work itself but it means that V8 can't inline the function calls. This is a slightly obfuscated version that should be faster:
Domain.prototype.run = function(fn) {
if (this._disposed)
return;
if (arguments.length >= 2) {
return this._runWithArgs(fn, Array.prototype.slice.call(arguments, 1));
} else {
return this._runNaked(fn);
}
};
Domain.prototype._runNaked = function (fn) {
this.enter();
var ret = fn.call(this);
this.exit();
return ret;
};
Domain.prototype._runWithArgs = function (fn, args) {
this.enter();
var ret = fn.apply(this, args);
this.exit();
return ret;
};
Sorry, something went wrong.
There was a problem hiding this comment.
This section of code from lib/events.js is probably the correct approach to take - https://github.com/iojs/io.js/blob/v0.12/lib/events.js#L110-L127
Sorry, something went wrong.
There was a problem hiding this comment.
I think we should have a standard function to handle the arguments in the most optimal way, something like this:
util.getArgumentsAsArray = function (args, slice) {
var length = args.length - slice;
var arr = new Array(length);
var index = slice;
while (index < length) {
arr[index - slice] = args[index];
index++;
}
return arr;
};
// or maybe ES6 Array.from() not sure about it
Array.from(arguments).slice(1);This function may be used in setTimeout(), setInterval(), setImmediate(), EventEmitter.emit(), domain.run(), in some future implementation with custom arguments and in third-party modules.
Sorry, something went wrong.
There was a problem hiding this comment.
@micnic how would you call this function without leaking the arguments from the caller?
Sorry, something went wrong.
There was a problem hiding this comment.
My understanding is that arguments are just a pain to deal with and that passing them to a function, like your getArgumentsAsArray(), is enough to cause a deoptimization in most cases.
Sorry, something went wrong.
There was a problem hiding this comment.
There's no way to slice or otherwise manipulate arguments without doing it manually if you want to avoid deopts. The only function that it is ok to pass a naked arguments to is Function.prototype.apply as it is special cased. Bluebird uses a macro to make this more convenient, also see https://github.com/petkaantonov/bluebird/wiki/Optimization-killers#3-managing-arguments for more info.
Sorry, something went wrong.
There was a problem hiding this comment.
@phpnode, ah, you are right, there is no way no avoid deoptimization, thanks for clarifying, I hope V8 devs will improve this.
I'll just add the loop manipulation as it is in the EventEmitter.
Sorry, something went wrong.
Adds the feature to define arguments for the function called in domain.run(), this is supposed to be useful when a function is called from another context and some values from the current context are needed as arguments, it's similar to the callback from setTimeout or setInterval.
|
This PR is ready for merge, I made the demanded changes |
Sorry, something went wrong.
|
@micnic @chrisdickinson will take it from here, he graciously volunteered to shepherd this PR. |
Sorry, something went wrong.
| Back | FazBrowse Home | New Git URL |
PR for nodejs/node-v0.x-archive#7193