【问题标题】:How to measure time taken by a function to execute如何测量函数执行所花费的时间
【发布时间】:2010-09-23 18:07:42
【问题描述】:

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

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

【问题讨论】:

  • 通常情况下,关于您试图通过执行时间完成的任务的陈述比单独回答问题要有用得多。如今,在 Firebug 或 Chrome 开发工具中使用 Profiling 通常是查找占用 CPU 资源的代码的更好方法。
  • performance.now() 在 Node.js 中不起作用。 new Date().getTime() 将在 Node 中工作。
  • @RyanWalker 甚至更简单的Date.now(),它也适用于节点
  • @oligofren - 有时您可能想要捕获这些数据。我有一种情况,我正在将其写入 indexedDB
  • 我想知道是否有任何最新文件(例如 2020/201 年)说 performance.now() 在节点中优于 Date.now() ?

标签: javascript profiling


【解决方案1】:

这是一个定时器功能。如果您想测量未嵌套的多个事物之间的时间:

function timer(lap){ 
    if(lap) console.log(`${lap} in: ${(performance.now()-timer.prev).toFixed(3)}ms`); 
    timer.prev = performance.now();
}

类似于 console.time(),但如果您不需要跟踪以前的计时器,则使用起来更方便。

如果你喜欢 console.time() 中的蓝色,你可以改用这条线

console.log(`${lap} in: %c${(performance.now()-timer.prev).toFixed(3)}ms`, 'color:blue');

用法:

timer()              // set the start
// do something 
timer('built')       // logs 'built in: 591.815ms'
// do something
timer('copied')      // logs 'copied in: 0.065ms'
// do something
timer('compared')    // logs 'compared in: 36.41ms'

【讨论】:

  • 注意!对于 NodeJS,您需要导入 performance: const { performance } = require('perf_hooks');
【解决方案2】:

使用这种代码格式

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

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

【讨论】:

    【解决方案3】:

    使用performance.now():

    var startTime = performance.now()
    
    doSomething()   // <---- measured code goes between startTime and endTime
        
    var endTime = performance.now()
    
    console.log(`Call to doSomething took ${endTime - startTime} milliseconds`)
    

    Node.js 中需要导入performance

    导入性能

    const { performance } = require('perf_hooks');
    

    使用 console.time:(living standard)

    console.time('doSomething')
        
    doSomething()   // <---- The function you're measuring time for 
        
    console.timeEnd('doSomething')
    

    注意:
    传递给time()timeEnd() 方法的字符串必须匹配
    计时器才能完成正如预期的那样)。

    console.time()文档:

    【讨论】:

    • Chrome 开发者工具现在也支持了。
    • 根据我的理解,这是目前收集准确时间的最佳方式。
    • 这两条语句之间的函数不需要执行吗?您现在测量定义它所花费的时间,而不是执行它。如果我错了,请纠正我...
    • 链接到 MDN 关于此功能的文章:developer.mozilla.org/en-US/docs/DOM/console.time
    • 是的,您可以执行 `totalTime += console.timeEnd('timer')' 并为每个计时器执行此操作
    【解决方案4】:

    这是一个计时函数的装饰器

    let timed = (f) => (...args) => {
        let start = performance.now();
        let ret = f(...args);
        console.log(`function ${f.name} took ${(performance.now() - start).toFixed(3)}ms`);
        return ret;   
    }
    

    用法:

    let test = () => { /* does something */ }
    test = timed(test)   // turns the function into a timed function in one line
    test()               // run your code as normal, logs 'function test took 1001.900ms' 
    

    如果您使用异步函数,您可以使 timed 异步并在 f(...args) 之前添加 await,这应该适用于这些函数。如果你想让一个装饰器同时处理同步和异步函数,那就更复杂了。

    【讨论】:

    • 这正是我想要的。谢谢!
    • 有没有什么办法让它也可以与异步函数一起使用?
    • 这很棒,有什么办法让它尊重 Typescript 类型?
    【解决方案5】:

    在函数前使用console.time('some label here'),在函数后使用console.timeEnd('some label here')。它会给你函数的运行时间。

    【讨论】:

    • 我投了赞成票,但这显然只对非常长/慢的函数有用:)
    【解决方案6】:

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

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

    【讨论】:

    • 谢谢,但是 +new Date() 中的 + 是什么?您可能会强制转换为 Number 吗?
    • @Bardelman 和 Number(new Date()) 完全一样。
    【解决方案7】:

    您还应该考虑阅读有关 bigO 表示法的内容。它可能比计时功能更好地了解正在发生的事情

    【讨论】:

    • 虽然与确定和衡量函数效率等相关,但这并不能真正回答问题,更多的是评论而不是答案。
    【解决方案8】:

    有多种方法可以实现这一目标:

    1. 使用 console.time

      console.time('function');
      //run the function in between these two lines for that you need to 
      //measure time taken by the function. ("ex. function();")
      console.timeEnd('function');
      
    2. 这是最有效的方法: 使用 performance.now(),例如

      var v1 = performance.now();
      //run the function here for which you have top measure the time 
      var v2 = performance.now();
      console.log("total time  taken = "+(v2-v1)+"milliseconds");
      
    3. 使用 +(add operator) 或 getTime()

      var h2 = +new Date(); //or
      var h2 = new Date().getTime();
      for(i=0;i<500;i++) { /* do something */}
      var h3 = +new Date();   //or 
      var h3 = new Date().getTime();
      var timeTaken = h3-h2;
      console.log("time ====", timeTaken);
      

    将一元加号运算符应用于 Date 实例时会发生以下情况: 获取有问题的 Date 实例的值 将其转换为数字

    注意:getTime() 提供比一元 + 运算符更好的性能。

    【讨论】:

      【解决方案9】:
      1. 启动计时器,请使用console.time("myTimer");
      2. 可选:打印经过的时间,请使用 console.timeLog("myTimer");
      3. 最后,停止计时器并打印决赛 时间:console.timeEnd("myTimer");

      您可以在MDNNode.js documentation 上阅读更多相关信息。

      适用于 Chrome、Firefox、Opera 和 NodeJS。 (不在 Edge 或 Internet Explorer 上)。

      【讨论】:

        【解决方案10】:

        有性能

        NodeJs:需要导入性能类

        var time0 = performance.now(); // Store the time at this point into time0
        
        yourFunction();   // The function you're measuring time for 
        
        var time1 = performance.now(); // Store the time at this point into time1
        
        console.log("youFunction took " + (time1 - time0) + " milliseconds to execute");
        

        使用控制台时间

        console.time('someFunction');
        
        someFunction(); // Whatever is timed goes between the two "console.time"
        
        console.timeEnd('someFunction');
        

        【讨论】:

          【解决方案11】:

          最好的方法是使用performance hooks 模块。虽然不稳定,但您可以mark 代码的特定区域和measure 标记区域之间的duration

          const { performance, PerformanceObserver } = require('perf_hooks');
          
          const measures = []
          
          const obs = new PerformanceObserver(list => measures.push(...list.getEntries()));
          obs.observe({ entryTypes: ['measure'] });
          const getEntriesByType = cb => cb(measures);
          
          const doSomething = val => {
            performance.mark('beginning of the process');
          
            val *= 2;
          
            performance.mark('after multiplication');
          
            performance.measure('time taken', 'beginning of the process', 'after multiplication');
          
            getEntriesByType(entries => {
              entries.forEach(entry => console.log(entry));
            })
          
            return val;
          }
          
          doSomething(4);
          

          试试here

          【讨论】:

            【解决方案12】:

            可以只使用一个变量:

            var timer = -performance.now();
            
            // Do something
            
            timer += performance.now();
            console.log("Time: " + (timer/1000).toFixed(5) + " sec.")
            

            timer/1000 - 将毫秒转换为秒

            .toFixed(5) - 修剪多余的数字

            【讨论】:

              【解决方案13】:

              具有累积周期的秒表

              与服务器和客户端(节点或 DOM)一起使用,使用 Performance API。 当您有许多小周期时很好,例如在一个调用 1000 次的函数中,该函数处理 1000 个数据对象,但您想查看此函数中的每个操作如何加总。

              所以这个使用了一个模块全局(单例)计时器。与类单例模式相同,只是使用起来更简单一些,但是您需要将其放在单独的例如stopwatch.js 文件。

              const perf = typeof performance !== "undefined" ? performance : require('perf_hooks').performance;
              const DIGITS = 2;
              
              let _timers = {};
              
              const _log = (label, delta?) => {
                  if (_timers[label]) {
                      console.log(`${label}: ` + (delta ? `${delta.toFixed(DIGITS)} ms last, ` : '') +
                          `${_timers[label].total.toFixed(DIGITS)} ms total, ${_timers[label].cycles} cycles`);
                  }
              };
              
              export const Stopwatch = {
                  start(label) {
                      const now = perf.now();
                      if (_timers[label]) {
                          if (!_timers[label].started) {
                              _timers[label].started = now;
                          }
                      } else {
                          _timers[label] = {
                              started: now,
                              total: 0,
                              cycles: 0
                          };
                      }
                  },
                  /** Returns total elapsed milliseconds, or null if stopwatch doesn't exist. */
                  stop(label, log = false) {
                      const now = perf.now();
                      if (_timers[label]) {
                          let delta;
                          if(_timers[label].started) {
                              delta = now - _timers[label].started;
                              _timers[label].started = null;
                              _timers[label].total += delta;
                              _timers[label].cycles++;
                          }
                          log && _log(label, delta);
                          return _timers[label].total;
                      } else {
                          return null;
                      }
                  },
                  /** Logs total time */
                  log: _log,
                  delete(label) {
                      delete _timers[label];
                  }
              };
              

              【讨论】:

                【解决方案14】:

                就我而言,我更喜欢使用@语法 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"
                    ]
                 }
                

                【讨论】:

                  【解决方案15】:
                  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;
                      }
                    }
                  }
                  

                  string相关的InitTime。

                  return Singleton.getInstance().initTime(label); // Returns the time init

                  return Singleton.getInstance().endTime(label); // Returns the total time between init and end

                  【讨论】:

                    【解决方案16】:

                    几个月前,我整理了自己的例程,使用 Date.now() 对函数计时——尽管当时接受的方法似乎是 performance.now()—— 因为性能对象在稳定的 Node.js 版本中尚不可用(内置)。

                    今天我做了更多的研究,发现了另一种计时方法。由于我还发现了如何在 Node.js 代码中使用它,所以我想在这里分享一下。

                    以下结合w3cNode.js给出的例子:

                    function functionTimer() {
                        performance.mark('start')
                        functionToBeTimed()
                        performance.mark('end')
                        performance.measure('Start to End', 'start', 'end')
                        const measure = performance.getEntriesByName('Start to End')[0]
                        console.log(measure.duration)
                    }
                    

                    注意:

                    如果您打算在 Node.js 应用程序中使用 performance 对象,则必须包含以下要求: const { performance } = require('perf_hooks')

                    【讨论】:

                    【解决方案17】:

                    也许对你有帮助。

                    var t0 = date.now(); doSomething(); var t1 = date.now(); console.log("Call to doSomething took approximate" + (t1 - t0)/1000 + " seconds.")

                    【讨论】:

                    • 虽然这段代码 sn-p 可以解决问题,including an explanation 确实有助于提高您的帖子质量。请记住,您正在为将来的读者回答问题,而这些人可能不知道您的代码建议的原因。也请尽量不要用解释性的 cmets 挤满你的代码,这会降低代码和解释的可读性!
                    【解决方案18】:

                    由于某些主要浏览器(即 IE10)不支持 console.timeperformance.now,因此我创建了一个利用最佳可用方法的超薄实用程序。但是,它缺乏对错误用法的错误处理(在未初始化的计时器上调用 End())。

                    使用它并根据需要改进它。

                    Performance: {
                        Timer: {},
                        Start: function (name) {
                            if (console && console.time) {
                                console.time(name);
                            } else if (window.performance.now) {
                                this.Timer[name] = window.performance.now();
                            } else {
                                this.Timer[name] = new Date().getTime();
                            }
                        },
                        End: function (name) {
                            if (console && console.time) {
                                console.timeEnd(name);
                            } else {
                                var result;
                                if (window.performance.now) {
                                    result = window.performance.now() - this.Timer[name];
                                } else {
                                    result = new Date().getTime() - this.Timer[name];
                                }
                                console.log(name + ": " + result);
                            }
                        }
                    }
                    

                    【讨论】:

                      【解决方案19】:

                      要获得精确值,您应该使用Performance interface。现代版本的 Firefox、Chrome、Opera 和 IE 都支持它。这是一个如何使用它的示例:

                      var performance = window.performance;
                      var t0 = performance.now();
                      doWork();
                      var t1 = performance.now();
                      console.log("Call to doWork took " + (t1 - t0) + " milliseconds.")
                      

                      Date.getTime()console.time() 不适合测量精确的执行时间。如果快速粗略估计适合您,您可以使用它们。通过粗略的估计,我的意思是您可以从实时获得 15-60 毫秒的偏移。

                      查看这篇精彩的 post 关于测量 JavaScript 执行时间的文章。作者还给出了几个关于 JavaScript 时间准确性的链接,值得一读。

                      【讨论】:

                        【解决方案20】:

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

                        var hrTime = process.hrtime()
                        console.log(hrTime[0] * 1000000 + hrTime[1] / 1000)
                        

                        【讨论】:

                        • 如果您宁愿将其转换为 ms e-3 而不是建议的微秒 e-6:hrtime[0] * 1000 + hrtime[1] / 1000000 -> 是的,我也宁愿使用 var hrtime! :P
                        【解决方案21】:

                        使用new Date().getTime()

                        getTime() 方法返回自 1970 年 1 月 1 日午夜以来的毫秒数。

                        例如

                        var start = new Date().getTime();
                        
                        for (i = 0; i < 50000; ++i) {
                        // do something
                        }
                        
                        var end = new Date().getTime();
                        var time = end - start;
                        alert('Execution time: ' + time);
                        

                        【讨论】:

                        • 请注意,您可以用 +new Date() 代替 getTime() 调用: var start = +new Date(); // do stuff alert("执行时间:"+(+new Date())-start);
                        • 时间不准确,因为日期不适用于此功能。我将在这里大胆地说,如果你想要准确的时间,你应该使用 vsync 的例子。虽然它只适用于 Chrome 和 Firefox ATM。
                        • 注意,getMilliseconds() 为您提供当前秒的毫秒分数。如果将 getTime() 替换为 getMilliseconds(),如果超过一秒,就会得到否定的结果。
                        • vsync 的答案按照今天的标准要正确得多,使用 Date() 可能会导致显示非常错误的结果,尤其是在 Windows 平台上,结果可能会四舍五入+下限到最接近的 15 毫秒边界,导致奇怪的东西,例如微小代码位上的 0ms 计时。
                        • @AshBlue,我们应该使用window.performance.now。见stackoverflow.com/a/15641427/632951
                        【解决方案22】:

                        谢谢,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]/1000000;。例如,

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

                        【讨论】:

                          【解决方案23】:

                          接受的答案是错误

                          由于 JavaScript 是异步的,所以接受的答案的变量 end 的值是错误的。

                          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

                          【讨论】:

                          • 不是因为for循环。 for 循环将一直等到最后一个循环,直到它继续执行您的源代码。 AJAX 调用是异步的。还有其他运行异步的函数。但是 for 循环不是异步执行的。
                          【解决方案24】:

                          不要使用日期()。阅读下文。

                          使用performance.now()

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

                          它适用于:

                          • IE 10 ++

                          • FireFox 15 ++

                          • Chrome 24 ++

                          • Safari 8 ++

                          • Opera 15 ++

                          • Android 4.4 ++

                          • etc, etc

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

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

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


                          另外,永远不要将Date 用于任何东西,因为它会受到“系统时间”变化的影响。这意味着当用户没有准确的系统时间时,我们得到无效结果——例如“负时间”:

                          2014 年 10 月,我的系统时钟出了故障,猜猜是什么....我打开 Gmail 并看到所有一天的电子邮件“发送 0 分钟以前”。而且我认为 Gmail 应该是由 Google 的世界级工程师构建的......

                          (将您的系统时钟设置为一年前,然后转到 Gmail,这样我们都可以开怀大笑。也许有一天我们会有一个 Hall of Shame 用于 JS Date。)

                          Google 电子表格的 now() 函数也存在这个问题。

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

                          【讨论】:

                          • 正是我想要的!我希望能够将多次相加,而控制台时间无法真正做到这一点。
                          • 请注意,Safari 尚不支持此功能:developer.mozilla.org/en-US/docs/Web/API/Performance.now()
                          • 我使用 Firebug Profile 和 performance.now(),它们都运行良好。 Performance.now() 从 Profile 中确认我的结果。
                          • 不适用于我最大的挂机,即 IE7(企业客户)。我不关心在 chrome 中测量性能,它总是快如闪电。
                          • 这是一个比 console.time() 更好的方法。
                          【解决方案25】:

                          如前所述,检查并使用内置计时器。但如果你想或需要自己写,这里是我的两分钱:

                          //=-=|Source|=-=//
                          /**
                           * JavaScript Timer Object
                           *
                           *      var now=timer['elapsed'](); 
                           *      timer['stop']();
                           *      timer['start']();
                           *      timer['reset']();
                           * 
                           * @expose
                           * @method timer
                           * @return {number}
                           */
                          timer=function(){
                              var a=Date.now();
                              b=0;
                              return{
                                  /** @expose */
                                  elapsed:function(){return b=Date.now()-a},
                                  start:function(){return a=Date.now()},
                                  stop:function(){return Date.now()},
                                  reset:function(){return a=0}
                              }
                          }();
                          
                          //=-=|Google Advanced Optimized|=-=//
                          timer=function(){var a=Date.now();b=0;return{a:function(){return b=Date.now()-a},start:function(){return a=Date.now()},stop:function(){return Date.now()},reset:function(){return a=0}}}();
                          

                          编译成功!

                          • 原始大小:压缩后 219 字节(未压缩 405 字节)
                          • 编译大小:压缩后 109 字节(未压缩 187 字节)
                          • gzip 压缩后的大小节省了 50.23%(不使用 gzip 时节省了 53.83%

                          【讨论】:

                            【解决方案26】:

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

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

                            要分析您的 JavaScript:

                            • Chrome 中,按 F12 并选择 Profiles 选项卡,然后收集 JavaScript CPU 配置文件。李>
                            • Firefox 中,安装/打开 Firebug,然后单击 Profile 按钮。
                            • IE 9+ 中,按 F12,点击 ScriptProfiler(取决于您的即)。

                            或者,在您的开发机器上,您可以使用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 对象只有毫秒分辨率,并且会受到任何操作系统的系统时钟变化的影响。在现代浏览器中,有更好的选择。

                            更好的选择是使用High Resolution Time,也就是window.performance.now()now() 在两个重要方面优于传统的Date.getTime()

                            1. now() 是具有亚毫秒分辨率的双精度数,表示自页面导航开始以来的毫秒数。它以小数形式返回微秒数(例如,1000.123 的值是 1 秒和 123 微秒)。

                            2. now() 单调递增。这很重要,因为Date.getTime() 可以可能在后续调用中向前甚至向后跳跃。值得注意的是,如果操作系统的系统时间被更新(例如原子钟同步),Date.getTime() 也会被更新。 now() 保证始终单调递增,因此不受操作系统系统时间的影响——它始终是挂钟时间(假设你的挂钟不是原子的……)。

                              李>

                            now() 几乎可以在new Date().getTime()+ new DateDate.now() 所在的所有地方使用。例外是 Datenow() 时间不能混合,因为 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;
                            }
                            

                            Chrome stable、Firefox 15+ 和 IE10 支持now()。还有几个polyfills 可用。

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

                            UserTiming 有 marks(时间戳)和 measures(持续时间)的概念。您可以根据需要定义任意多个,它们会显示在 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 可用(我写的)。

                            【讨论】:

                            • 优秀和最新的答案恕我直言 :) 稍加编辑会更好。我想说,用户计时不是测量的“另一种选择”,而是当基准测试未在开发机器本身上完成时的 首选选项。使用您的 polyfill,它适用于所有浏览器。隐藏performance.nowDate 的细节和样板是它存在的原因。
                            【解决方案27】:
                            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() 是可选的 - 只需将 false 传递给 StopWatch 构造函数即可。

                            【讨论】:

                              【解决方案28】:

                              要进一步扩展 vsync 的代码,以便能够在 NodeJS 中将 timeEnd 作为值返回,请使用这段代码。

                              console.timeEndValue = function(label) { // Add console.timeEndValue, to add a return value
                                 var time = this._times[label];
                                 if (!time) {
                                   throw new Error('No such label: ' + label);
                                 }
                                 var duration = Date.now() - time;
                                 return duration;
                              };
                              

                              现在像这样使用代码:

                              console.time('someFunction timer');
                              
                              someFunction();
                              
                              var executionTime = console.timeEndValue('someFunction timer');
                              console.log("The execution time is " + executionTime);
                              


                              这为您提供了更多可能性。您可以存储执行时间以用于更多目的,例如在方程式中使用它,或存储在数据库中,通过 websockets 发送到远程客户端,在网页上提供服务等。

                              【讨论】:

                                【解决方案29】:

                                使用 Firebug,同时启用 Console 和 Javascript。单击配置文件。重新加载。再次单击配置文件。查看报告。

                                【讨论】:

                                • 好建议,但显然只适用于 FF。我们经常想比较浏览器速度... :-)
                                • 在新的 Firebuq 上,他们将此选项隐藏到菜单中,使用 CTRL + SHIFT + P 或 console.profile();控制台..profileEnd()
                                • Chrome 现在也支持console.time()console.timeEnd()
                                猜你喜欢
                                • 1970-01-01
                                • 2014-05-25
                                • 2020-07-30
                                • 1970-01-01
                                • 1970-01-01
                                • 2014-09-05
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多