我有一个使用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");
    }
  });
}
 


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

评论

只需读取db调用之前的开始时间,然后在回调内部查看结束时间即可。

数据库完成插入的时间和执行回调的时间可能不同,这会在测量中引入错误?

不,您不必担心,如果数据库库代码设计合理,并且在触发回调之前未处理任何其他操作,则应该采取适当的措施。您还可以通过将时间戳记放置在实际执行插入操作的库代码中来配置插入文件,而不是您自己的插入文件,但是同样,我也不用担心

我建议您尝试使用NodeTime,它似乎非常适合您要尝试的操作。

我编写了与console.time()类似的timerlog,但具有其他功能; github.com/brillout/timerlog

#1 楼

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


评论


干净的内置节点解决方案。

–贝鲁尔
2013年9月23日在20:28

>我想知道如何测量这些数据库插入操作所花费的时间。 --- console.timeEnd(“ dbsave”)仅输出以控制时间。您不能再使用它,并且灵活性较差。如果您需要实际的计时值,例如原始问题,则不能使用console.timeEnd(“ dbsave”)

– gogaman
2014年8月6日在18:42



@gogaman这是一个好方法,因为您无法捕获console.timeEnd()的输出。将输出通过管道传输到文件并从那里使用可能会有用吗?

– Doug Molineux
2014年9月25日下午21:16

那么以下答案中的console.time()和process.hrtime()有什么区别?

–黄色圣人
15年2月20日在14:43

值得一提的是,然后打印出执行时间,以便现在有新用户。

– janko-m
2015年11月10日下午13:13

#2 楼

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


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

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


评论


它在任何方面都优于console.time解决方案吗?

–胆小
15年3月31日在17:29

是的,它要精确得多,您可以将结果存储在变量中

–达拉斯·克拉克
2015年7月1日在6:17

这对我有用,因为我想多次调用计时器

–tbh__
17年1月13日在16:00

为什么要两次调用process.hrtime(start)?是否有特定原因?

–索爱尔(Sohail Si)
19年2月6日在19:09

process.hrtime([time]),其中time是一个可选参数,必须是前一个对diff与当前时间的process.hrtime()调用的结果。它给出了当前通话和之前的通话时间之间的差异。

– Nilesh Jain
19年11月28日在8:50



#3 楼

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

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

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


有关更多信息,请参阅console.time上的Mozilla开发人员文档。

评论


这对接受的答案有什么影响?

– Dan Dascalescu
18年7月5日在23:11

我的答案使用我的代码后,修改了接受的答案

– jfcorugedo
18年7月6日在14:21

#4 楼

惊讶的是没有人提到新的内置库:
可在Node> = 8.5中使用,并且应该位于现代浏览器中
https://developer.mozilla.org/en-US/docs/Web / API / Performance
https://nodejs.org/docs/latest-v8.x/api/perf_hooks.html#
Node 8.5〜9.x(Firefox,Chrome)



 // 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);
  // apparently you should clean up...
  performance.clearMarks();
  performance.clearMeasures();         
  // Prints the number of milliseconds between Mark 'A' and Mark 'B'
})(); 




https://repl.it/@CodyGeisler/NodeJsPerformanceHooks
Node 12.x
https://nodejs.org/docs/latest-v12.x/​​api/ perf_hooks.html
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);
      // apparently you should clean up...
      performance.clearMarks();
      // performance.clearMeasures(); // Not a function in Node.js 12
});
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);
    }
})();


评论


给我TypeError:Performance.getEntriesByName不是Node v10.4.1中的函数

–杰里米·蒂尔(Jeremy Thille)
18年7月29日在7:47

我做了这个示例,以便您可以在线运行它。它是节点9.7.1。如果它在v10.4.1中不起作用,那么我想知道可能会发生什么变化!

–科迪G
18年7月29日在22:07

稳定性:1-也许是实验性的? :) nodejs.org/docs/latest-v8.x/api / ...

–杰里米·蒂尔(Jeremy Thille)
18年7月30日在6:33

是的,肯定已经改变了。 v10中有一个新的观察者,您可以在nodejs.org/docs/latest-v10.x/api/documentation.html上查看文档。如果有机会,我会更新的!

–科迪G
18年8月3日在17:38

太好了,虽然一件事是developer.mozilla.org/en-US/docs/Web/API/Performance/measure指示我们应该将performance.clearMarks()以及performance.clearMeasures()一起使用吗?

– Craig van Tonder
11月17日22:39



#5 楼

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

使用process.hrtime()作为@ D.Deriso建议,以下是我更简单的方法: />
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;
}


#6 楼

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


评论


我必须查找语法'+ new Date()'来找出含义。根据对此答案的评论(stackoverflow.com/a/221565/5114),出于性能和可读性的考虑,使用该表格不是一个好主意。我更喜欢一些冗长的内容,以便读者阅读。另请参阅以下答案:stackoverflow.com/a/5036460/5114

– Mnebuerquo
2015年1月19日在19:08



我经常使用var start = process.hrtime(); ... var end = process.hrtime(start);获得高分辨率时间(如果我需要低于毫秒的精度)

–安德烈·西多罗夫(Andrey Sidorov)
2015年1月20日下午5:57

#7 楼

旧问题,但需要一个简单的API和轻量级解决方案;您可以使用内部使用高分辨率实时(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的回答启发,编写了该模块。此处的文档。

#8 楼

您可以尝试Benchmark.js。它支持许多平台,其中也包括node.js。

评论


如果您可以在此用例中添加如何使用Benchmark.js的示例,那将很好。

–佩塔
16年6月22日在22:02

#9 楼

您也可以尝试exectimer。它为您提供反馈,例如:您的代码可以像这样包装:

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


#10 楼

从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()函数,它可以提供高分辨率的实时图像。

希望有帮助。