【问题标题】:Loop time execution in JavascriptJavascript中的循环时间执行
【发布时间】:2016-01-06 06:21:54
【问题描述】:

让我们以下面的 sn-p 为例:

var len = 1000000,
    testArr = []

    for (var i = 0; i < len; i++) {
        testArr.push(i+1)
    }

    function mprofile(name, subject, object) {
        var start = new Date().getTime(),
            result = subject(object),
            end = new Date().getTime() - start
        console.log(name)
        console.log('Result: ' + result)
        console.log(end)
    }

    var length = testArr.length,
        start = new Date().getTime(),
        cnt = 0

    for (i = 0; i < length; i++) {
        cnt += testArr[i]
    }

    console.log('Regular loop:')
    console.log('Result: ' + cnt)
    console.log(new Date().getTime() - start);

    start = new Date().getTime()
    cnt = i = 0
    for (i = length; i--; ) {
        cnt += testArr[i]
    }

    console.log('Reversered loop')
    console.log('Result: ' + cnt)
    console.log(new Date().getTime() - start);

    start = new Date().getTime()
    cnt = i = 0
    var startAt = length%8,
        iterations = Math.floor((length+7) / 8)

    do {
        switch (startAt) {
            case 0: cnt += testArr[i++]
            case 7: cnt += testArr[i++]
            case 6: cnt += testArr[i++]
            case 5: cnt += testArr[i++]
            case 4: cnt += testArr[i++]
            case 3: cnt += testArr[i++]
            case 2: cnt += testArr[i++]
            case 1: cnt += testArr[i++]
        }
        startAt = 0
    } while(--iterations)

    console.log('Duffs device')
    console.log('Result: ' + cnt)
    console.log(new Date().getTime() - start);

    start = new Date().getTime()
    cnt = i = 0
    iterations = Math.floor((length+7) / 8)

    switch (length % 8) {
        case 0: cnt += testArr[i++]
        case 7: cnt += testArr[i++]
        case 6: cnt += testArr[i++]
        case 5: cnt += testArr[i++]
        case 4: cnt += testArr[i++]
        case 3: cnt += testArr[i++]
        case 2: cnt += testArr[i++]
        case 1: cnt += testArr[i++]
    }

    while(--iterations) {
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
        cnt += testArr[i++]
    }

    console.log('Optimized Duffs device')
    console.log('Result: ' + cnt)
    console.log(new Date().getTime() - start);


    mprofile(
        'Profiled regular loop',
        function(arr) {
            var cnt = 0,
                length = arr.length
            for (i = 0; i < length; i++) {
                cnt += testArr[i]
            }
            return cnt
        },
        testArr
    )

    mprofile(
        'Profiled reversed loop',
        function(arr) {
            var cnt = 0,
                length = arr.length
            for (i = length; i--; ) {
                cnt += testArr[i]
            }
            return cnt
        },
        testArr
    )

    mprofile(
        'Profiled Duffs device',
        function(arr) {
            var cnt = i = 0,
                length = arr.length,
                startAt = length%8,
                iterations = Math.floor((length+7) / 8)

            do {
                switch (startAt) {
                    case 0: cnt += arr[i++]
                    case 7: cnt += arr[i++]
                    case 6: cnt += arr[i++]
                    case 5: cnt += arr[i++]
                    case 4: cnt += arr[i++]
                    case 3: cnt+ = arr[i++]                     
                       case 2: cnt += arr[i++]
                    case 1: cnt += arr[i++]
                }
                startAt = 0
            } while(--iterations)
            return cnt
        },
        testArr
    )

    mprofile(
        'Profiled optimized Duffs device',
        function(arr) {
            var cnt = i = 0,
                length = arr.length,
                iterations = Math.floor((length+7) / 8)

            switch (length % 8) {
                case 0: cnt += arr[i++]
                case 7: cnt += arr[i++]
                case 6: cnt += arr[i++]
                case 5: cnt += arr[i++]
                case 4: cnt += arr[i++]
                case 3: cnt += arr[i++]
                case 2: cnt += arr[i++]
                case 1: cnt += arr[i++]
            }

            while(--iterations) {
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
                cnt += arr[i++]
            }
            return cnt
        },
        testArr
    )

普通循环与回调内部执行的循环之间报告的执行时间存在差异。此外,如果您在 head 中的脚本标记 中运行它与在 开发者控制台 中执行它,执行时间会有所不同,如下图所示:

  1. 脚本标签的结果:

  2. 来自控制台 (Firefox) 的结果:

谁能解释为什么会发生这种情况或提供任何资源的链接,我可以在其中找到与此相关的任何信息。如果您将链接的响应或文档中涵盖浏览器差异,也将不胜感激。

感谢您的时间和帮助。

【问题讨论】:

  • 您能否至少解释一下这是做什么的,有什么区别,为什么不应该有任何区别?我所看到的只是迭代一百万次,添加东西等,一个浏览器比另一个更高效,这并不令人惊讶,这些数字是毫秒,如果两个不同的浏览器设法使用完全相同的时间,那将是惊人的
  • 称为循环优化。您应该看到几种不同的处理数组循环的技术。 问题在于在全局范围内执行相同算法与将其作为回调执行的区别。为什么不能在执行时间上存在差异很简单,因为逻辑是相同的。顺便说一句,这是来自同一浏览器 Firefox 的示例。
  • 请注意,通常 Duff 的设备在大多数解释语言中不是很有用。它的用处在于,在汇编/机器语言中,可执行代码中不存在标签(它只存在于编译器生成代码),因此一系列不间断的标签看起来与指令序列没有什么不同。 Duff 的设备基本上破解了 C 的 switch 语句实现,该语句通常编译为跳转表。在解释型语言中,情况可能并非如此。
  • 所以这两个结果都来自控制台,但后者是直接在控制台中运行代码,而前者是从 HTML 文件中运行代码,你想知道为什么它们是不一样吗?
  • @slebetman 是的,你是对的,但如图所示,它实际上提供了生产力的小幅提高。问题是为什么算法的执行方式和结束时间之间存在很大差异。因为逻辑没有变化。例如,为什么从回调内部调用相同算法而不是全局范围时,循环花费的时间会更少。

标签: javascript performance


【解决方案1】:
  • performance.now() 是衡量性能的最佳选择。

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

  • 结束时间计算错误。在你的mprofile 函数中,你在调用第一个console.log 之前计算一个差异,用普通代码 - 在第二个之后。因此,在一种情况下,您将与控制台的交互包含在您的测量中,在另一种情况下 - 不是

  • 另外,整个示例有点不正确。您应该创建一个类似loopreverseLoop 等的函数,并在调用它们之前/之后测量时间。那么您应该测量回调中相同功能的时间。您应该至少运行每个案例 10 次并检查平均时间。

【讨论】:

    【解决方案2】:

    如果您使用的是 Chrome,console.time() 非常有用。 例如:

    console.time('myTime1')
    console.timeEnd('myTime1') //myTime1: 5047.492ms
    

    【讨论】:

    • 我也试过这种方法。它仍然报告相同的行为。区别在于它比使用 new new Date().getTime() 更精确一些
    • 也适用于 firefox 和 IE11 以及 Edge 和 Opera 和 Safari - 所以,几乎任何有用的浏览器都有它
    猜你喜欢
    • 2018-11-08
    • 2013-10-15
    • 1970-01-01
    • 2015-01-02
    • 2014-07-27
    • 2018-02-04
    • 1970-01-01
    • 1970-01-01
    • 2011-12-18
    相关资源
    最近更新 更多