我有一个应用程序,我必须将很多值推送到数组,所以我测试执行时间:
var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
a.push(i);
}
var ed = new Date().getTime();
console.info((ed - st) / 1000);
console.info(a.length);
我直接在Firefox控制台和Chrome控制台中运行代码,费用为37 seconds
。在执行过程中,即使鼠标也可以在Chrome中移动,但没有交互效果。
然后我改变了代码:
function push() {
var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
a.push(i);
}
var ed = new Date().getTime();
console.info((ed - st) / 1000);
console.info(a.length);
}
var tr = setTimeout(push, 50);
简化将代码放入函数中,并使用setTimeout
调用它,费用为0.844 second
。在执行期间,我可以正常在Chrome中操作。
这里发生了什么?
我知道setTimeout
会将控件放到浏览器上来执行UI作业,这会使页面响应。例如,当我在页面的鼠标移动期间进行一些计算时,我会将计算执行延迟以防止它阻止UI。
但为什么它会减少相同代码的总执行时间?
答案 0 :(得分:5)
在执行期间,我可以正常在Chrome中操作。
不正确。主要的镀铬窗口将与其他情况一样冷冻(仅适用于较短的时间)。调试工具是一个单独的线程,但不会减慢速度。
但为什么它会减少相同代码的总执行时间?
如果你在dev工具中运行它会。如果您实际执行代码,VM可以进行属性优化,则时间可比(近1秒)。例如
var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
a.push(i);
}
var ed = new Date().getTime();
console.info('normal', (ed - st) / 1000);
console.info(a.length);
function push() {
var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
a.push(i);
}
var ed = new Date().getTime();
console.info('timeout', (ed - st) / 1000);
console.info(a.length);
}
var tr = setTimeout(push, 0);
http://jsfiddle.net/gu9Lg52j/您会看到normal
执行与setTimeout
一样快。
此外,如果您将代码包装在函数中并在控制台中执行,即使没有setTimeout
,时间也是可比较的,因为VM可以在函数定义和执行之间进行优化:
function push() {
var st = new Date().getTime();
var a = [];
for (var i = 0; i < 20971520; i++) {
a.push(i);
}
var ed = new Date().getTime();
console.info('timeout', (ed - st) / 1000);
console.info(a.length);
}
push();
答案 1 :(得分:2)
代码的两种变体应该以几乎相同的速度运行(后一个示例可能更快,但速度不快10倍)。
在Chrome开发者工具中,有一个不同的故事。表达式在with
块内进行评估。这意味着首先在另一个对象(__commandLineAPI
)内搜索a
和i
等变量。这会增加额外的开销,导致执行时间延长10倍。
答案 2 :(得分:1)
所有JavaScript引擎都执行各种优化。例如,V8使用2个编译器,一个默认使用的简单编译器和一个优化编译器。优化编译器未编译的代码慢,非常慢。
优化编译器运行的条件是代码必须在(不太长)函数(there are other conditions)中。您在控制台中尝试的第一个代码不在函数中。将您的第一个代码放在一个函数中,你会看到它的表现与第二个相同,setTimeout
不会改变任何内容。
当主要性能因素是优化编译时,检查控制台中的性能是没有意义的。如果您的目标是节点,请使用基准测试框架。如果您要定位浏览器,请使用jsperf等网站。
现在,当你必须在浏览器中进行一个非常长的计算时(这里似乎不是这种情况),你应该考虑在不影响UI的后台线程中完成工作的using web workers
答案 3 :(得分:0)
setTimeout
不会加快阵列创建速度,而会锁定浏览器。如果您担心阵列创建期间的浏览器锁定, Web worker (请参阅MDN)可能会解决问题。这是一个使用Web worker为您的代码进行的jsFiddle演示。工作人员代码在html中:
onmessage = function (e) {
var a = [], now = new Date;
for (var i=0; i<20971520; i++) {
a.push(i);
}
postMessage({timings: 'duration: '+(new Date()-now) +
'Ms, result: [' + a[0] + '...'+a[a.length-1] + ']'});
}