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

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


当前回答

公认的答案是错误的!

由于JavaScript是异步的,因此接受的答案的变量端的值将是错误的。

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
// JavaScript is not waiting until the for is finished !!
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time); 

for的执行速度可能非常快,因此您无法看到结果是错误的。您可以使用执行某些请求的代码来测试它:

var start = new Date().getTime();

for (i = 0; i < 50000; ++i) {
  $.ajax({
    url: 'www.oneOfYourWebsites.com',
    success: function(){
       console.log("success");
    }
  });
}

var end = new Date().getTime();
var time = end - start;
alert('Execution time: ' + time); 

因此,警报将非常迅速地提示,但在控制台中,您将看到ajax请求正在继续。

以下是您应该如何做到的:https://developer.mozilla.org/en-US/docs/Web/API/Performance.now

其他回答

如果需要在本地开发机器上获取函数执行时间,可以使用浏览器的分析工具,也可以使用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可用(我写的)。

不要使用Date()。阅读以下内容。

使用performance.now():

<script>
var a = performance.now();
alert('do something...');
var b = performance.now();
alert('It took ' + (b - a) + ' ms.');
</script>

它适用于:

即10++火狐15++铬24++Safari 8++歌剧15++Android 4.4++等等

console.time对你来说可能可行,但它是非标准的§:

此功能是非标准的,不在标准轨道上。不要在面向Web的生产网站上使用它:它不会对每个用户都有效。实现之间也可能存在很大的不兼容性,并且行为可能会在未来发生变化。

除了浏览器支持之外,performance.now似乎有可能提供更准确的计时,因为它似乎是console.time的基本版本。


<rant>此外,不要将Date用于任何事情,因为它会受到“系统时间”变化的影响。这意味着当用户没有准确的系统时间时,我们将得到无效的结果,如“负计时”:

2014年10月,我的系统时钟失控了,猜猜怎么了。。。。我打开Gmail,看到我一天的所有电子邮件都是“0分钟前发送的”。我还以为Gmail应该是由谷歌的世界级工程师建造的。。。。。。。

(将你的系统时钟设置为一年前,然后转到Gmail,这样我们都可以开怀大笑。也许有一天,我们会为JS Date举办一个“耻辱大厅”。)

Google Spreadsheet的now()函数也存在此问题。

您将使用Date的唯一时间是您想向用户显示其系统时钟时间的时间。当你想得到时间或测量任何东西时,就不会这样。

process.hrtime()在Node.js中可用-它返回以纳秒为单位的值

let hrTime = process.hrtime()
console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
export default class Singleton {

  static myInstance: Singleton = null;

  _timers: any = {};

  /**
   * @returns {Singleton}
   */
  static getInstance() {
    if (Singleton.myInstance == null) {
      Singleton.myInstance = new Singleton();
    }

    return this.myInstance;
  }

  initTime(label: string) {
    this._timers[label] = Date.now();
    return this._timers[label];
  }

  endTime(label: string) {
    const endTime = Date.now();
    if (this._timers[label]) {
      const delta = endTime - this._timers[label];
      const finalTime = `${label}: ${delta}ms`;
      delete this._timers[label];
      return finalTime;
    } else {
      return null;
    }
  }
}

与字符串相关的InitTime。

return Singleton.getInstance().initTime(标签);//返回时间init

return Singleton.getInstance().endTime(标签);//返回初始化和结束之间的总时间

在我的例子中,我更喜欢使用@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"
    ]
 }