我需要以毫秒为单位获取执行时间。

我最初问这个问题是在2008年。当时接受的答案是使用newDate().getTime()。然而,我们现在都可以同意使用标准performance.now()API更合适。因此,我将接受的答案改为这个答案。


当前回答

谢谢,Achim Koellner,我会把你的答案扩大一点:

var t0 = process.hrtime();
//Start of code to measure

//End of code
var timeInMilliseconds = process.hrtime(t0)[1]/1000000; // dividing by 1000000 gives milliseconds from nanoseconds

请注意,除了要测量的内容之外,您不应该做其他任何事情(例如,console.log也需要时间执行,这会影响性能测试)。

注意,按照异步函数执行时间的顺序,应该插入var timeInMilliseconds=process.hrtime(t0)[1]/10000;在回调中。例如

var t0 = process.hrtime();
someAsyncFunction(function(err, results) {
var timeInMilliseconds = process.hrtime(t0)[1]/1000000;

});

其他回答

如果需要在本地开发机器上获取函数执行时间,可以使用浏览器的分析工具,也可以使用console.time()和console.timeEnd()等控制台命令。

所有现代浏览器都内置JavaScript分析器。这些分析器应该提供最准确的度量,因为您不必修改现有代码,这可能会影响函数的执行时间。

要评测JavaScript:

在Chrome中,按F12并选择配置文件选项卡,然后收集JavaScript CPU配置文件。在Firefox中,安装/打开Firebug,然后单击Profile按钮。在IE 9+中,按F12,单击脚本或探查器(取决于您的IE版本)。

或者,在您的开发机器上,您可以使用console.time()和console.timeEnd()向代码中添加检测。Firefox11+、Chrome2+和IE11+支持的这些函数报告通过console.time()启动/停止的计时器。time()将用户定义的计时器名称作为参数,然后timeEnd()报告计时器启动后的执行时间:

function a() {
  console.time("mytimer");
  ... do stuff ...
  var dur = console.timeEnd("myTimer"); // NOTE: dur only works in FF
}

注意,只有Firefox在timeEnd()调用中返回经过的时间。其他浏览器只需将结果报告给开发人员控制台:timeEnd()的返回值未定义。

如果您想在野外获得函数执行时间,则必须对代码进行检测。你有两个选择。您可以通过查询new Date().getTime()来简单地保存开始和结束时间:

function a() {
  var start = new Date().getTime();
  ... do stuff ...
  var end = new Date().getTime();
  var dur = end - start;
}

然而,Date对象只有毫秒分辨率,并且会受到任何操作系统系统时钟变化的影响。在现代浏览器中,有一个更好的选项。

更好的选择是使用高分辨率时间,也就是window.performance.now().nnow()在两个重要方面优于传统的Date.getTime():

now()是一个具有亚毫秒分辨率的double,表示自页面导航开始以来的毫秒数。它以小数形式返回微秒数(例如,1000.123的值为1秒和123微秒)。now()单调递增。这一点很重要,因为Date.getTime()可能会在后续调用中向前或向后跳转。值得注意的是,如果OS的系统时间被更新(例如原子时钟同步),Date.getTime()也会被更新。now()保证总是单调递增的,所以它不受操作系统系统时间的影响——它将始终是墙上的时钟时间(假设你的墙上的时钟不是原子的…)。

now()几乎可以用于newDate().getTime()、+newDate和tDate.now()所在的所有位置。例外的是Date和now()时间不混合,因为Date基于unix epoch(1970年以来的毫秒数),而now(()是页面导航开始后的毫秒数(因此它将比Date小得多)。

下面是如何使用now()的示例:

function a() {
  var start = window.performance.now();
   ... do stuff ...
  var end = window.performance.now();
  var dur = end - start;
}

now()在Chrome稳定版、Firefox 15+和IE10中受支持。也有几种多边形填充可用。

在野外测量执行时间的另一个选项是UserTiming。UserTiming的行为类似于console.time()和console.timeEnd(),但它使用了now()使用的相同的高分辨率时间戳(因此您会得到一个亚毫秒单调递增的时钟),并将时间戳和持续时间保存到PerformanceTimeline。

UserTiming具有标记(时间戳)和度量(持续时间)的概念。您可以根据需要定义任意多个,并且它们将在PerformanceTimeline上显示。

要保存时间戳,请调用mark(startMarkName)。要获得自第一次标记以来的持续时间,只需调用measure(measurename,startMarkname)。然后将持续时间与标记一起保存在PerformanceTimeline中。

function a() {
  window.performance.mark("start");
  ... do stuff ...
  window.performance.measure("myfunctionduration", "start");
}

// duration is window.performance.getEntriesByName("myfunctionduration", "measure")[0];

UserTiming在IE10+和Chrome25+中可用。还有一个polyfill可用(我写的)。

var StopWatch = function (performance) {
    this.startTime = 0;
    this.stopTime = 0;
    this.running = false;
    this.performance = performance === false ? false : !!window.performance;
};

StopWatch.prototype.currentTime = function () {
    return this.performance ? window.performance.now() : new Date().getTime();
};

StopWatch.prototype.start = function () {
    this.startTime = this.currentTime();
    this.running = true;
};

StopWatch.prototype.stop = function () {
    this.stopTime = this.currentTime();
    this.running = false;
};

StopWatch.prototype.getElapsedMilliseconds = function () {
    if (this.running) {
        this.stopTime = this.currentTime();
    }

    return this.stopTime - this.startTime;
};

StopWatch.prototype.getElapsedSeconds = function () {
    return this.getElapsedMilliseconds() / 1000;
};

StopWatch.prototype.printElapsed = function (name) {
    var currentName = name || 'Elapsed:';

    console.log(currentName, '[' + this.getElapsedMilliseconds() + 'ms]', '[' + this.getElapsedSeconds() + 's]');
};

基准

var stopwatch = new StopWatch();
stopwatch.start();

for (var index = 0; index < 100; index++) {
    stopwatch.printElapsed('Instance[' + index + ']');
}

stopwatch.stop();

stopwatch.printElapsed();

输出

Instance[0] [0ms] [0s]
Instance[1] [2.999999967869371ms] [0.002999999967869371s]
Instance[2] [2.999999967869371ms] [0.002999999967869371s]
/* ... */
Instance[99] [10.999999998603016ms] [0.010999999998603016s]
Elapsed: [10.999999998603016ms] [0.010999999998603016s]

performance.now()是可选的-只需向StopWatch构造函数传递false。

在我的例子中,我更喜欢使用@grammar suger并用babel编译它。这种方法的问题是函数必须位于对象内部。

JS代码示例

function timer() {
    return (target, propertyKey, descriptor) => {
        const start = Date.now();
        let oldFunc = descriptor.value;

        descriptor.value = async function (){
            var result = await oldFunc.apply(this, arguments);
            console.log(Date.now() - start);
            return result;
        }
    }
}

// Util function 
function delay(timeout) {
    return new Promise((resolve) => setTimeout(() => {
        resolve();
    }, timeout));
}

class Test {
    @timer()
    async test(timout) {
        await delay(timout)
        console.log("delay 1");
        await delay(timout)
        console.log("delay 2");
    }
}

const t = new Test();
t.test(1000)
t.test(100)

babelrc(用于babel 6)

 {
    "plugins": [
        "transform-decorators-legacy"
    ]
 }

使用此代码格式

const startTime =new Date().getTime();

//do something 
const endTime = new Date().getTime();
console.log(`time taken ${(endTime - startTime)/1000} seconds`);

一个简单的解决方案,您也可以在这里使用加法运算符

 var start = +new Date();
 callYourFunctionHere();
 var end = +new Date();
 var time = end - start;
 console.log('total execution time = '+ time + 'ms');