关于performance.now()来测试函数的执行时间

时间:2015-08-12 02:25:57

标签: javascript performance-testing

我目前正在创建一个简短的javascript演示,仅用于检查功能性能目的。代码如下:

(function(){
	'use strict';
	
	var getFunctionExecuteTime = function(myFoo) {
		if(typeof myFoo !== 'function'){
			return -1;
		}else{
			var t1 = performance.now();
			myFoo();
			var t2 = performance.now();
						
			return t2-t1;
		}
	};
	
	var foo = function() {
		console.log('running.');	
	};
	
	function foo2(){
		console.log('running by foo2.');
	}
	
	console.log('function foo2 spent time: ', getFunctionExecuteTime(foo2));
	console.log('function foo spent time: ', getFunctionExecuteTime(foo));
	console.log('function --- spent time: ', getFunctionExecuteTime(function(){
		console.log('running.');
	}));
})();

我想测试的这三个函数,它们的执行时间假设接近,但我得到的Chrome控制台的输出很有趣,如下所示:

由foo2运行。 功能foo2花费的时间:5.1000000021304

运行。 功能foo花费时间:0.11000000085914508

运行。 功能---花费时间:0.115999995614402

即使我交换了函数的顺序,第一个总是花费更多的时间来执行,所以有人能给我一个暗示真正发生的事情吗?

1 个答案:

答案 0 :(得分:4)

快速解答:

这是引擎V8优化Javascript代码的方式。

  1. 第一次运行函数时,Javascript代码直接转换为机器代码,可以立即执行。

  2. 调用另一个线程来处理优化步骤。现在,JavaScript代码变成了中间字节代码。

  3. 下次调用该函数时,将调用优化的代码。

您可以阅读更多here

调查步骤:

这是我对Node.js环境的调查:

  1. 如果您这样更改函数调用的顺序:
console.log('function foo spent time: ', getFunctionExecuteTime(foo));
console.log('function foo2 spent time: ', getFunctionExecuteTime(foo2));

结果:foo将比foo2花费更长的时间。

running.
function foo spent time:  2.8903000000864267
running by foo2.
function foo2 spent time:  0.10759999975562096
running.
function --- spent time:  0.058200000785291195
  1. 有趣的是,如果您运行以下代码:
const { performance } = require('perf_hooks');

const perf = () => {
  const t1 = performance.now();
  const t2 = performance.now();

  return t2 - t1;
};

for (let i = 0; i < 10; i++) {
  console.log(`Called ${i + 1} times. Time spent: ${perf()}`);
}

结果:同一函数的第一次调用总是比其他函数花费更长的时间。

Called 1 times. Time spent: 0.4595999997109175
Called 2 times. Time spent: 0.026399999856948853
Called 3 times. Time spent: 0.018099999986588955
Called 4 times. Time spent: 0.0015000002458691597
Called 5 times. Time spent: 0.0015000002458691597
Called 6 times. Time spent: 0.0014000004157423973
Called 7 times. Time spent: 0.0021000001579523087
Called 8 times. Time spent: 0.0034999996423721313
Called 9 times. Time spent: 0.002199999988079071
Called 10 times. Time spent: 0.0027000000700354576
  1. 这是我想到的两件事:

    • Node.js的事件循环花费很少的时间来初始化,检查条件,...
    • 或者这就是V8引擎(在Chrome和Node.js中都用于编译Javascript代码)优化代码的方式。

    因此,要弄清楚,这是对上面的代码的一个小修改:


const { performance } = require('perf_hooks');

console.log('Waiting 1...');
console.log('Waiting 2...');
console.log('Waiting 3...');
console.log('Waiting 4...');
console.log('Waiting 5...');

const perf = () => {
  const t1 = performance.now();
  const t2 = performance.now();

  return t2 - t1;
};

for (let i = 0; i < 10; i++) {
  console.log(`Called ${i + 1} times. Time spent: ${perf()}`);
}

结果:

Waiting 1...
Waiting 2...
Waiting 3...
Waiting 4...
Waiting 5...
Called 1 times. Time spent: 0.8381999991834164
Called 2 times. Time spent: 0.00279999990016222
Called 3 times. Time spent: 0.0024000005796551704
Called 4 times. Time spent: 0.0026000002399086952
Called 5 times. Time spent: 0.00279999990016222
Called 6 times. Time spent: 0.0018000006675720215
Called 7 times. Time spent: 0.021200000308454037
Called 8 times. Time spent: 0.001600000075995922
Called 9 times. Time spent: 0.0014000004157423973
Called 10 times. Time spent: 0.001499999314546585
  1. 结论:

    因此,很明显,这就是V8引擎的工作方式。您的getFunctionExecuteTime函数已在此处进行了优化。