Javascript分析之谜 - 闭包变量
Javascript profiling mystery - closure variables
我正在测试在闭包中定义变量的情况下的性能(使用 chrome 时间线(。因此,它的值不会向用户公开。
正如预期的那样,run_proto_fn
运行速度快了几倍,垃圾回收最少,内存堆也很低。
但run_proto_obj
恰好恰恰相反,好像在对象原型属性属性中使用非函数值的成本很高。
有人可以在这里分享一些澄清吗?
SOME = function(){};
SOME.prototype.exe = function(v){
var x = {
a:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
b:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
c:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
};
return x[v];
};
SOME2 = function(){};
SOME2.prototype.exe = function(v){
return this.exes[v];
};
SOME2.prototype.exes = {
a:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
b:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
c:'Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?Lorem ipsum dolor sit amet, consectetur adipisicing elit. Ea, quae repudiandae eveniet cumque consequatur vitae aut. Nisi perspiciatis magnam explicabo optio reprehenderit dignissimos at porro quam, neque dolorum, architecto odit?',
};
SOME_FN = function(){};
SOME_FN.prototype.exe = function(v){
var x = {
a: function(p){this.p1 = p;return this;},
b:function(p){this.p2 = p*3;return this;},
c:function(p){this.p3 = p*99;return this;},
};
return x[v].call(this,42);
};
SOME_FN2 = function(){};
SOME_FN2.prototype.exe = function(v){
return this.exes[v].call(this,42);
};
SOME_FN2.prototype.exes = {
a: function(p){this.p1 = p;return this;},
b:function(p){this.p2 = p*3;return this;},
c:function(p){this.p3 = p*99;return this;},
};
var a1 = a2 = a_fn1 = a_fn2 = [];
var run_local_obj = function(){
for (var i = 1000000 - 1; i >= 0; i--) {
x1 = new SOME();
x1.exe('a');
a1.push(x1);
}
};
var run_proto_obj = function(){
for (var i = 1000000 - 1; i >= 0; i--) {
x2 = new SOME2();
x2.exe('a');
a2.push(x2);
}
};
var run_local_fn = function(){
for (var i = 1000000 - 1; i >= 0; i--) {
x1 = new SOME_FN();
x1.exe('a');
x1.exe('b');
x1.exe('c');
a_fn1.push(x1);
}
};
var run_proto_fn = function(){
for (var i = 1000000 - 1; i >= 0; i--) {
x2 = new SOME_FN2();
x2.exe('a');
x2.exe('b');
x2.exe('c');
a_fn2.push(x2);
}
};
<button onclick="run_local_obj(this)">local obj</button>
<button onclick="run_proto_obj(this)">proto obj</button>
<button onclick="run_local_fn(this)">local obj FN</button>
<button onclick="run_proto_fn(this)">proto obj</button>
我听过一句话:
每次函数运行时定义闭包变量
但是,我仍然没有雾。
我尝试运行测量,首先我注意到的是,仅使用您问题中的代码很难理解发生了什么。
如果我一个接一个地运行这些测试(单击按钮并查看时间线(,那么对于下一次运行,结果会有很大差异。从几次运行来看,第三(run_local_fn
(通常比其他运行更长。
然后我尝试以倒序运行它们(从 4 到 1 单击按钮(并得到完全不同的结果 - run_local_obj
最长。
所以我稍微修改了测试代码,以便能够获得稳定的结果。
完整代码在这里,您可以克隆存储库并在本地进行测试。
以下是我在 Chrome 中运行每个测试的方式(我使用 js-perf-test
文件夹中的python -m SimpleHTTPServer 8082
启动了它(:
- 使用 http://localhost:8082/perf.html 打开选项卡,打开开发工具
- 开始时间线录制
- 单击按钮
- 在控制台中等待结果(最小值/最大值/平均值(
- 停止时间线录制
结果稳定且可重复(时序和时间线视图(,以下是测试之一:
- "run_local_obj" - 508.45ms,时间轴
- "run_proto_obj" - 433.11ms,时间轴
- "run_local_fn" - 756.26ms,时间轴
- "run_proto_fn" - 560.62ms,时间轴
所以我们在这里看到的是:
1(run_proto_obj
最快,run_local_obj
接近它。
我认为run_proto_obj
应该是最有效的,因为它使用带有字符串的静态定义的对象。而且JS引擎可能能够优化run_local_obj
,所以x
对象是重用的,而不是每次都创建的。
2(run_local_fn
最慢。
这里我们有本地x
对象和动态字符串计算,比其他测试更floating
部分。
3(run_proto_fn
比run_local_fn
快,但比前两个函数慢。
我认为这也是意料之中的,带有a, b, c
的对象只定义一次(因此它比run_local_fn
快(。
与前两个函数相比,它动态计算生成的字符串,因此速度较慢。
所以回到你的问题:
正如预期的那样,run_proto_fn运行速度快了几倍,垃圾回收最少,内存堆也很低。 但run_proto_obj恰好恰恰相反,好像在对象原型属性属性中使用非函数值的成本很高。
在我看来,您只是没有正确设置实验。根据上面的结果,run_proto_obj
实际上是最快的。
更新:我刚刚在Firefox中尝试了相同的测试,结果相似:
- "run_local_obj" - 344.85ms
- "run_proto_obj" - 151.47ms
- "run_local_fn" - 788.08毫秒
- "run_proto_fn" - 265.21ms
run_proto_obj
最快,run_local_fn
最慢。
- 子类访问父类's闭包变量
- 构造函数函数闭包变量
- 如何冻结函数's在闭包中的变量
- 使变量可用于不带闭包的异步调用
- 局部变量在闭包中丢失
- 其中是闭包中存储的变量-堆栈或堆
- javascript闭包:保护内部变量
- Javascript:附加字符串中的事件,闭包中的变量求值
- "可变变量可从闭包“”访问;在传递给Array.prototype.every的函数中
- JavaScript闭包和变量引用
- Javascript分析之谜 - 闭包变量
- 对闭包变量的更改是否在使用闭包的回调中可见
- 使用object.assign()添加到对象中的getter发现闭包变量的值错误
- Javascript:为什么对闭包变量的访问可能很慢
- 模块中未更新Nodejs闭包变量
- node.js捕获闭包变量
- Javascript中绑定闭包变量
- 函数外部的Javascript闭包变量访问
- 回调函数访问闭包变量
- 为什么我的闭包变量在使用$后被清除.每个都使用JSON数据