我如何通过回调衡量JavaScript代码的执行时间?

问题描述 投票:300回答:11

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

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

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

javascript node.js profiling
11个回答
682
投票

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

console.timeEnd()

1
投票

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

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

对于Azure,请使用以下方法:exectimer

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

希望这会有所帮助。


0
投票

另一个选择是使用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 工具:

express-debug是用于express的开发工具。这是一种简单的中间件,它以无障碍的方式将有用的调试输出注入到html中。

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

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

也。要添加到以上答案中,您可以选中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 以仅针对开发环境启用任何性能分析代码。


198
投票

有一种为此设计的方法。签出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");}
};

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

process.hrtime();

这里是一个可以在终端(BASH shell)中运行的快速测试:

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
}

64
投票

调用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); 将记录当前时间(以毫秒为单位),然后调用for i in {1..100}; do echo $i; curl http://localhost:8080/; done 将显示从该点开始的持续时间。

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

console.time('label')

有关更多信息,请参见console.timeEnd('label')


20
投票

惊讶的是没有人提到新的内置库:

在节点> = 8.5中可用,并且应该在现代浏览器中可用

console.time('test'); //some code console.timeEnd('test'); //Prints something like that-> test: 11374.004ms

Mozilla's developer docs on console.time

Node 8.5〜9.x(Firefox,Chrome)

console.time

https://developer.mozilla.org/en-US/docs/Web/API/Performance

节点10.x

https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#

// const { performance } = require('perf_hooks'); // enable for node
const delay = time => new Promise(res=>setTimeout(res,time))
async function doSomeLongRunningProcess(){
  await delay(1000);
}
performance.mark('A');
(async ()=>{
  await doSomeLongRunningProcess();
  performance.mark('B');
  performance.measure('A to B', 'A', 'B');
  const measure = performance.getEntriesByName('A to B')[0];
  // firefox appears to only show second precision.
  console.log(measure.duration);
  performance.clearMeasures(); // apparently you should remove entries...
  // Prints the number of milliseconds between Mark 'A' and Mark 'B'
})();

18
投票

对于任何想要获取经过时间而不是控制台输出的值:

使用https://repl.it/@CodyGeisler/NodeJsPerformanceHooks作为@ D.Deriso建议,以下是我更简单的方法:

https://nodejs.org/docs/latest-v10.x/api/perf_hooks.html

16
投票
const { PerformanceObserver, performance } = require('perf_hooks');
const delay = time => new Promise(res => setTimeout(res, time))
async function doSomeLongRunningProcess() {
    await delay(1000);
}
const obs = new PerformanceObserver((items) => {
    console.log('PerformanceObserver A to B',items.getEntries()[0].duration);
    performance.clearMarks();
});
obs.observe({ entryTypes: ['measure'] });

performance.mark('A');

(async function main(){
    try{
        await performance.timerify(doSomeLongRunningProcess)();
        performance.mark('B');
        performance.measure('A to B', 'A', 'B');
    }catch(e){
        console.log('main() error',e);
    }
})();

9
投票

老问题,但需要一个简单的API和轻量级解决方案;您可以使用process.hrtime()在内部使用高分辨率实时(function functionToBeMeasured() { var startTime = process.hrtime(); // do some task... // ...... var elapsedSeconds = parseHrtimeToSeconds(process.hrtime(startTime)); console.log('It takes ' + elapsedSeconds + 'seconds'); } function parseHrtimeToSeconds(hrtime) { var seconds = (hrtime[0] + (hrtime[1] / 1e9)).toFixed(3); return seconds; } )。

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");
          }
    });
}

请注意,每次调用perfy时,该实例都会自动销毁。

公开:受process.hrtime启发编写了此模块。文件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)); }


2
投票

您可以尝试perfy.end(label)。它支持许多平台,其中也包括node.js。


2
投票

您也可以尝试D.Deriso's answer。它为您提供反馈,例如:

here

[edit]现在甚至有一种更简单的方法来使用exectimer,因为它现在可以包装要测量的代码。您的代码可以像这样包装:

Benchmark.js
© www.soinside.com 2019 - 2024. All rights reserved.