如何使用回调测量 JavaScript 代码的执行时间?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10617070/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-24 02:10:40  来源:igfitidea点击:

How do I measure the execution time of JavaScript code with callbacks?

javascriptnode.jsprofiling

提问by Stormshadow

I have a piece of JavaScript code that I am executing using the node.jsinterpreter.

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

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

How can I measure the time taken by these database insert operations? I could compute the difference of date values after and before this piece of code but that would be incorrect because of the asynchronous nature of the code.

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

回答by user2362662

Use the Node.js console.time()and console.timeEnd():

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

回答by D.Deriso

There is a method that is designed for this. Check out process.hrtime();.

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

So, I basically put this at the top of my app.

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

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
}

Then I use it to see how long functions take. Here's a basic example that prints the contents of a text file called "output.txt":

然后我用它来查看函数需要多长时间。这是一个打印名为“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);

Here's a quick test you can run in a terminal (BASH shell):

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

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

回答by jfcorugedo

Invoking console.time('label')will record the current time in milliseconds, then later calling console.timeEnd('label')will display the duration from that point.

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

The time in milliseconds will be automatically printed alongside the label, so you don't have to make a separate call to console.log to print a label:

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

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

For more information, see Mozilla's developer docs on console.time.

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

回答by Cody G

Surprised no one had mentioned yet the new built in libraries:

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

Available in Node >= 8.5, and should be in Modern Browers

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

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

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

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

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

Node 8.5 ~ 9.x (Firefox, Chrome)

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

https://repl.it/@CodyGeisler/NodeJsPerformanceHooks

https://repl.it/@CodyGeisler/NodeJsPerformanceHooks

Node 10.x

节点 10.x

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

https://nodejs.org/docs/latest-v10.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);
    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);
    }
})();

回答by Sing

For anyone want to get time elapsed value instead of console output :

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

use process.hrtime()as @D.Deriso suggestion, below is my simpler approach :

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

回答by Andrey Sidorov

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

回答by Onur Y?ld?r?m

Old question but for a simple API and light-weight solution; you can use perfywhich uses high-resolution real time (process.hrtime) internally.

老问题,但对于简单的 API 和轻量级解决方案;您可以使用 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));
}

Note that each time perfy.end(label)is called, that instance is auto-destroyed.

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

Disclosure: Wrote this module, inspired by D.Deriso's answer. Docs here.

披露:编写此模块,灵感来自D.Deriso 的回答。文档在这里

回答by Alexandru Savin

You could also try exectimer. It gives you feedback like:

你也可以试试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

[edit] There is even a simpler way now to use exectimer because now it can wrap the code to be measured. Your code could wrapped like this:

[编辑] 现在有一种更简单的方法来使用 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

回答by jsbeckr

You could give Benchmark.jsa try. It supports many platforms among them also node.js.

你可以试试Benchmark.js。它支持许多平台,其中还有 node.js。

回答by Manohar Reddy Poreddy

I had same issue while moving from AWS to Azure

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

For express & aws, you can already use, existing time() and timeEnd()

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

For Azure, use this: https://github.com/manoharreddyporeddy/my-nodejs-notes/blob/master/performance_timers_helper_nodejs_azure_aws.js

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

These time() and timeEnd() use the existing hrtime() function, which give high-resolution real time.

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

Hope this helps.

希望这可以帮助。