【问题标题】:Javascript/JSPerf Looping PerformanceJavascript/JSPerf 循环性能
【发布时间】:2016-01-12 18:50:08
【问题描述】:

最近我一直在深入研究 JS 性能,而我的另一个问题 Javascript Array Performance 导致我遇到了这个问题。

问题: 使用全局变量进行循环似乎比使用局部变量进行迭代要快得多,任何人都可以向我解释一下,为什么会这样? --- 这只是我对 JSPerf 理解的错误,但问题 2 仍然存在,但我想没有真正的答案,其余的已经在聊天中与 @Igor-Raush 讨论过 --- 或者我想, JSPerf 中的测试仍然快 100 倍,然后是基本版本...

  • 我很确定这不是局部变量创建

您可以在这里看到这种行为:http://jsperf.com/fastest-array-loops-in-javascript/420 -- 我添加了最后两个测试,但最后一个由于某种原因没有工作,所以我删除了它的内容

问题 2(额外问题,有点相关): 为什么当您单独在 JSPerf 上运行测试时(对于其中一些),它们的性能始终完全不同,而不是同时运行它们? (你可以在 While length--test 上看到这个)


我正在测试这个,因为(如果你去我的另一个问题),我不相信在测试中循环我的数组应该像它一样慢。

【问题讨论】:

    标签: javascript arrays performance


    【解决方案1】:

    问题 1

    全局情况下性能“提高”的巨大原因是您在准备代码中初始化了一个全局it = 0。在 JSPerf 中,每个测试用例都会运行多次试验。第一次运行测试用例时,它会递增全局it,直到超过arr.length

    下一次(以及所有后续时间)测试用例运行时,条件it < arr.length 的计算结果为false,甚至没有进入循环。这不是在“While loop, basic”测试用例中的情况,其中var i = 0 在每次试验之前都被初始化。

    您可以在Plunker 中看到,使用全局迭代器变量的速度大约是使用本地迭代器变量的两倍(打开控制台查看结果)。

    问题 2

    性能差异很大的一个可能原因是,运行所有测试可能会导致阵列在运行后面的测试用例时缓存在更靠近 CPU 的位置。当您独立运行测试用例时,它可能需要内存访问。对于像for/while 迭代这样基本的东西, 内存访问是一个真正的瓶颈。然而,这只是一种可能的解释。

    【讨论】:

    • 1.哦,该死的,你是绝对正确的,这完全让我忘记了,出于某种原因,我认为 jsperf 会在每次迭代之间“重新启动”所有使用的变量,我傻了,对不起。 (我刚刚检查过,在迭代之间拆解不起作用) 2. 我明白了,这可以解释它,但是加速约 300 倍?我想我需要尝试为另一个问题中的超慢搜索找到另一种解释,这真的让我很困扰,运行 .get 函数会产生非常有希望的结果,但是在循环内的测试函数中运行相同的函数(即使使用一次迭代)很慢。
    • 我发现在单独运行“While length--”案例与运行所有测试时相比,速度降低了 20-25%。
    • 也不要低估由于缓存未命中导致的减速。展示缓存和空间局部性效果的一个著名示例是有序迭代与反向迭代。请参阅此Plunker。在一个好的优化编译器上,按序迭代对缓存更加友好,因为它将数组的块预加载到缓存中。我在 Chrome 中看到的加速大约是 3 万倍!
    • 这是最奇怪的事情,因为,我将在这里复制所有测试的结果 - 309,169,504 ops/sec 独立 - 490,824 ops/sec 是的,我看到类似 600x 的速度减慢,漂亮很奇怪,你不觉得吗?
    • 没错,我知道,但是在这种情况下,Firefox 正在做一些超级时髦的事情,我一点也不明白。我不知道为什么缓存不友好的递减循环会比正常循环更快。
    猜你喜欢
    • 1970-01-01
    • 2012-04-02
    • 2016-03-25
    • 2015-03-21
    • 1970-01-01
    • 2014-03-12
    • 2017-09-19
    • 1970-01-01
    • 2013-09-09
    相关资源
    最近更新 更多