admin管理员组文章数量:1404938
I read in various places that it's advisable to be careful with the arguments
object and that this is ok...
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
But, is this ok or not?...
function makeArray (l) {
var i = l.length, array = new Array(i);
while (i--) array[i] = l[i];
return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
var args = makeArray (arguments);
callback.apply(args[0] = this, args);
};
What is meant by "leaking arguments" and how does it affect optimisation?
I am focused on V8, but I assume it applies to other pilers as well?
to prove it works...
function makeArray (l) {
var i = l.length, array = new Array(i);
while (i--) array[i] = l[i];
return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
var args = makeArray (arguments);
callback.apply(args[0] = this, args);
};
o.m = "Hello, ";
function test(f, n) {
alert(this.m + " " + n)
}
o.f(test, "it works...")
I read in various places that it's advisable to be careful with the arguments
object and that this is ok...
var i = arguments.length, args = new Array(i);
while (i--) args[i] = arguments[i];
But, is this ok or not?...
function makeArray (l) {
var i = l.length, array = new Array(i);
while (i--) array[i] = l[i];
return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
var args = makeArray (arguments);
callback.apply(args[0] = this, args);
};
What is meant by "leaking arguments" and how does it affect optimisation?
I am focused on V8, but I assume it applies to other pilers as well?
to prove it works...
function makeArray (l) {
var i = l.length, array = new Array(i);
while (i--) array[i] = l[i];
return array;
};
//...
//EDIT: put the function on an object to better represent the actual case
var o = {};
o.f = function (callback) {
var args = makeArray (arguments);
callback.apply(args[0] = this, args);
};
o.m = "Hello, ";
function test(f, n) {
alert(this.m + " " + n)
}
o.f(test, "it works...")
Share
edited May 14, 2015 at 15:13
Cool Blue
asked May 14, 2015 at 10:23
Cool BlueCool Blue
6,4767 gold badges30 silver badges70 bronze badges
5
-
Instead of
var o={}; o.f=function(){ [code] };
, you should havevar o={f:function(){ [code] }};
. – Ismael Miguel Commented May 14, 2015 at 14:47 - In fact they are equivalent ;) – Cool Blue Commented May 14, 2015 at 15:15
- Yes, they are. But the difference is that you are creating an object with a method using the code I provived. With your code, you create an empty object and then you modify it to insert a new method. – Ismael Miguel Commented May 14, 2015 at 16:53
- Well, the end result is the same. I did it that way to more closely model the actual code that I'm analysing. I'm aware that there are a few ways to do it but why do you remend doing it the way you suggest? Any particular reason? – Cool Blue Commented May 14, 2015 at 17:13
- There are 2 advantages that e to my mind: 1- The most basic one is the syntax itself. You can declare every method and property right there, without any changes. You don't need to fiddle around to look where the heck a method/property is being defined. 2- Since you do everything at once, the piler may optimize the code when creating the object and when any method/property is accessed. – Ismael Miguel Commented May 14, 2015 at 17:48
2 Answers
Reset to default 9The problem with arguments
is same as with local eval
and with
: they cause aliasing. Aliasing defeats all sorts of optimizations so even if you enabled optimization of these kind of functions you would probably end up just wasting time which is a problem with JITs because the time spent in the piler is time not spent running code (although some steps in the optimization pipeline can be run in parallel).
Aliasing due to arguments
leaking:
function bar(array) {
array[0] = 2;
}
function foo(a) {
a = 1;
bar(arguments);
// logs 2 even though a is local variable assigned to 1
console.log(a);
}
foo(1);
Note that strict mode eliminates this:
function bar(array) {
array[0] = 2;
}
function foo(a) {
"use strict";
a = 1;
bar(arguments);
// logs 1 as it should
console.log(a);
}
foo(1);
Strict mode however isn't optimized either and I don't know any reasonable explanation except that benchmarks don't use strict mode and strict mode is rarely used. That might change since many es6 features require strict mode, otoh arguments
is not needed in es6 so...
This is a 2-fold problem:
- You lose any and all possible optimizations and branch predictions
Thearguments
object is unpredictible. - You leak memory. Really bad!
Consider the following code (run it at your own risk!):
function a(){return arguments;}
x=a(document.getElementsByTagName('*'));
window._interval=setInterval(function(){
for(var i=0;i<1e6;i++)
{
x=a(x);
}
},5000);
*{font-family:sans-serif;}
<p>Warning! This may overheat your cpu and crash your browser really badly!</p>
<p>I'm not responsible for any software and hardware damages!</p>
<p><b>Run at your own risk!!!</b></p>
<p>If you ran this code, press F5 to stop or close the browser.</p>
<p>If you want, you can try to <button onclick="window.clearInterval(window._interval);window.x='';">stop it</button>. (the RAM may remain unchanged)</p>
And now watch your RAM go up, when you run that (it goes up at a rate of around 300-500MB every 5 seconds).
A naive implementation that simply passes the arguments around may cause these problems.
Not to mention that your code will (generally) be a tad slower.
Note that this:
function a(){return arguments;}
function b(arg){return arg;}
x=a(document.getElementsByTagName('*'));
window._interval=setInterval(function(){
for(var i=0;i<1e6;i++)
{
x=b(x);
}
},5000);
*{font-family:sans-serif;}
<p>This may be safe, but be careful!</p>
<p>I'm not responsible for any software and hardware damages!</p>
<p><b>Run at your own risk!!!</b></p>
<p>If you ran this code, press F5 to stop or close the browser.</p>
<p>If you want, you can try to <button onclick="window.clearInterval(window._interval);window.x='';">stop it</button>.</p>
Won't have the same effect as the code before.
This is because b()
returns the same variable, instead of a new reference to a new arguments
object.
This is a very important difference.
本文标签: javascript V8 optimisation and quotleaking argumentsquotStack Overflow
版权声明:本文标题:javascript V8 optimisation and "leaking arguments" - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744861168a2629077.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论