我有一段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");
    }
  });
}

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


当前回答

调用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开发者文档。

其他回答

令人惊讶的是,还没有人提到图书馆的新建:

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

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

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

节点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

节点12.倍

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

可以使用包装器函数轻松地报告任何现有函数的执行时间。

包装器用于扩展现有函数,以便在现有函数执行之前和之后执行某些操作——这是一种组合逻辑的方便方法。

下面是一个使用withDurationReporting包装器的例子:

// without duration reporting
const doSomethingThatMayTakeAWhile = async (someArg: string, anotherArg: number) => { 
  /** your logic goes here */
}

// with duration reporting
const doSomethingThatMayTakeAWhileWithReporting = withDurationReporting(
  'doSomethingThatMayTakeAWhile', 
  doSomethingThatMayTakeAWhile
);
// note: you can define the function with duration reporting directly, too
const doSomethingThatMayTakeAWhile = withDurationReporting(
  'doSomethingThatMayTakeAWhile', 
  async (someArg: string, anotherArg: number) => { 
    /** your logic goes here */
  }
)

这是包装器本身:

import { hrtime } from 'process';

const roundToHundredths = (num: number) => Math.round(num * 100) / 100; // https://stackoverflow.com/a/14968691/3068233

/**
 * a wrapper which reports how long it took to execute a function, after the function completes
 */
export const withDurationReporting = <R extends any, T extends (...args: any[]) => Promise<R>>(
  title: string,
  logic: T,
  options: {
    reportingThresholdSeconds: number;
    logMethod: (message: string, metadata?: Record<string, any>) => void;
  } = {
    reportingThresholdSeconds: 1, // report on anything that takes more than 1 second, by default
    logMethod: console.log, // log with `console.log` by default
  }, 
) => {
  return (async (...args: Parameters<T>): Promise<R> => {
    const startTimeInNanoseconds = hrtime.bigint();
    const result = await logic(...args);
    const endTimeInNanoseconds = hrtime.bigint();
    const durationInNanoseconds = endTimeInNanoseconds - startTimeInNanoseconds;
    const durationInSeconds = roundToHundredths(Number(durationInNanoseconds) / 1e9); // https://stackoverflow.com/a/53970656/3068233
    if (durationInSeconds >= options.reportingThresholdSeconds)
      options.logMethod(`${title} took ${durationInSeconds} seconds to execute`, { title, durationInSeconds });
    return result;
  }) as T;
};

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

现在有一种更简单的方法来使用exectime。你的代码可以这样包装:

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

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

老问题,但一个简单的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));
}

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

披露:受D.Deriso的回答启发,编写了这个模块。文档。