如何用callback来测量JavaScript代码的执行时间

我有一段JavaScript代码,我正在执行使用node.js解释器。

for(var i = 1; i < LIMIT; i++){ db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) { if( err || !saved ) console.log("Error"); else console.log("Saved"); }); } 

我想知道如何测量这些数据库插入操作所花费的时间。 我可以计算这段代码之前和之后的Date值的差异,但由于代码的asynchronous性质,这可能是不正确的。

使用Node.js console.time()console.timeEnd()

 var i; console.time("dbsave"); for(i = 1; i < LIMIT; i++){ db.users.save({id : i, name : "MongoUser [" + i + "]"}, end); } end = function(err, saved) { console.log(( err || !saved )?"Error":"Saved"); if(--i === 1){console.timeEnd("dbsave");} }; 

有一种方法是为此而devise的。 查看process.hrtime(); 。

所以,我基本上把它放在我的应用程序的顶部。

 var start = process.hrtime(); var elapsed_time = function(note){ var precision = 3; // 3 decimal places var elapsed = process.hrtime(start)[1] / 1000000; // divide by a million to get nano to milli console.log(process.hrtime(start)[0] + " s, " + elapsed.toFixed(precision) + " ms - " + note); // print message + time start = process.hrtime(); // reset the timer } 

然后我用它来看看函数需要多长时间。 这是一个基本的例子,它打印一个名为“output.txt”的文本文件的内容:

 var debug = true; http.createServer(function(request, response) { if(debug) console.log("----------------------------------"); if(debug) elapsed_time("recieved request"); var send_html = function(err, contents) { if(debug) elapsed_time("start send_html()"); response.writeHead(200, {'Content-Type': 'text/html' } ); response.end(contents); if(debug) elapsed_time("end send_html()"); } if(debug) elapsed_time("start readFile()"); fs.readFile('output.txt', send_html); if(debug) elapsed_time("end readFile()"); }).listen(8080); 

下面是一个可以在terminal(BASH shell)中运行的快速testing:

 for i in {1..100}; do echo $i; curl http://localhost:8080/; done 

调用console.time('label')将以毫秒为单位logging当前时间,稍后调用console.timeEnd('label')将显示从该点开始的持续时间。

以毫秒为单位的时间将自动打印在标签旁边,因此您不必单独调用console.log来打印标签:

 console.time('test'); //some code console.timeEnd('test'); //Prints something like that-> test: 11374.004ms 
 var start = +new Date(); var counter = 0; for(var i = 1; i < LIMIT; i++){ ++counter; db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) { if( err || !saved ) console.log("Error"); else console.log("Saved"); if (--counter === 0) { var end = +new Date(); console.log("all users saved in " + (end-start) + " milliseconds"); } }); } 

老问题,但一个简单的API和轻量级的解决scheme; 您可以使用内部使用高分辨率实时( process.hrtime )的perfy

 var perfy = require('perfy'); function end(label) { return function (err, saved) { console.log(err ? 'Error' : 'Saved'); console.log( perfy.end(label).time ); // <——— result: seconds.milliseconds }; } for (var i = 1; i < LIMIT; i++) { var label = 'db-save-' + i; perfy.start(label); // <——— start and mark time db.users.save({ id: i, name: 'MongoUser [' + i + ']' }, end(label)); } 

请注意,每次perfy.end(label) ,该实例都会自动销毁。

披露:在D.Deriso的答案的启发下写了这个模块。 文档在这里 。

对于任何想要获得时间stream逝值而不是控制台输出的人:

使用process.hrtime()作为@ D.Derisobuild议,下面是我更简单的方法:

 foo(); function foo() { var start = process.hrtime(); setTimeout(function () { var seconds = parseHrtimeToSeconds(process.hrtime(start)); console.log('foo takes ' + seconds + 'seconds'); //foo takes 3.457seconds //logToFile('foo takes' + seconds + 'seconds'); }, 3456); } function parseHrtimeToSeconds(hrtime) { var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3); return seconds; } 

你可以试试Benchmark.js 。 它支持其中的许多平台也node.js.

你也可以尝试执行者 。 它给你的反馈如下:

 var t = require("exectimer"); var myFunction() { var tick = new t.tick("myFunction"); tick.start(); // do some processing and end this tick tick.stop(); } // Display the results console.log(t.timers.myFunction.duration()); // total duration of all ticks console.log(t.timers.myFunction.min()); // minimal tick duration console.log(t.timers.myFunction.max()); // maximal tick duration console.log(t.timers.myFunction.mean()); // mean tick duration console.log(t.timers.myFunction.median()); // median tick duration 

现在有更简单的方法来使用exectimer,因为现在它可以包装要测量的代码。 你的代码可以像这样包装:

 var t = require('exectimer'), Tick = t.Tick; for(var i = 1; i < LIMIT; i++){ Tick.wrap(function saveUsers(done) { db.users.save({id : i, name : "MongoUser [" + i + "]"}, function(err, saved) { if( err || !saved ) console.log("Error"); else console.log("Saved"); done(); }); }); } // Display the results console.log(t.timers.myFunction.duration()); // total duration of all ticks console.log(t.timers.saveUsers.min()); // minimal tick duration console.log(t.timers.saveUsers.max()); // maximal tick duration console.log(t.timers.saveUsers.mean()); // mean tick duration console.log(t.timers.saveUsers.median()); // median tick duration 

我会build议尝试NodeTime ,这似乎是一个很好的适合你正在做的事情。

另一种select是使用快速debugging工具:

express-debug是一个快速开发工具。 这是一个简单的中间件,以非阻碍的方式将有用的debugging输出注入到您的html中。

它方便地提供了一个configuration面板:

总请求处理时间。 中间件,参数和路由时间。

也。 添加上面的答案,你可以检查这个答案 ,只为开发环境启用任何分析代码。

从AWS转移到Azure时,我遇到了同样的问题

对于express和aws,已经可以使用现有的time()和timeEnd()

对于Azure,使用这个: https : //github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_azure_aws.js

这些time()和timeEnd()使用现有的hrtime()函数,它提供了高分辨率的实时性。

希望这可以帮助。