【问题标题】:Why are so many Array.prototype (iteration) methods so slow? [duplicate]为什么这么多 Array.prototype(迭代)方法这么慢? [复制]
【发布时间】:2018-01-20 00:54:15
【问题描述】:

我决定评估我项目中的所有 for 循环,看看是否可以用 Array.prototype 方法替换它 - 其中 75% 可以轻松替换。在开始替换之前,我想我可能会进行一些测试。 在我的机器上,大多数原型方法比 polyfill 慢得多(~80%)

使用常规 for 循环,这些测试中的每一个都更快

我没有时间查找其他 jsperf 测试,但我确信大多数原型方法会更慢。 那为什么?这些函数非常有用,但是为什么它们这么多比简单的 for 循环慢。

Chrome 60.0.3112 / Windows 10 0.0.0

【问题讨论】:

  • 我猜这是由于为每个数组项调用函数(新范围/上下文)所涉及的开销。对我来说,原生函数是如此之快(例如,array.some 的 7400 万次操作/秒)以至于用户不会看到任何差异,而且不编写/维护我自己的函数所节省的时间是值得的。
  • 大多数测试都有缺陷,因为它们只是在做不同的事情(例如,concat 创建一个新数组与push 添加到现有数组)。此外,您的 find 测试从根本上被其 return 函数外的语句破坏。

标签: javascript arrays


【解决方案1】:

除非 js 被解析并且我们永远不知道实际执行的机器代码是什么样的,否则它可能是检查高级算法效率以将其转换为汇编的好方法。

1) 一个常规的 for 循环:

loop:
  CP A,100 //the exit statement
  JP z,end // exit

  LD A,123//some random math
  LD B,124
  ADD A,B
  LD 123,A

  JP loop //the actual loop     

end:

2) 原型函数:

Array_forEach:
loop:
  CP A,B //the exit statement
  JP z,end // exit

  LD 123,A//remove values from direct registers
  LD 124,B

  LD arg1,array_length //prepare function environment
  LD arg2,A

  CALL anonymous_func

  LD A,123
  LD B,124

  JP loop //the actual loop

anonymous_func:
  LD A,123//some random math
  LD B,124
  ADD A,B
  LD 123,A
  RET

如您所见,forEach 使用了一些昂贵的 CALL,更不用说上下文更改了。


但是,解析器甚至可能不会让两者都运行到那么深的层次,或者它做了一些非常好的内联,这意味着 forEach 实际上有时比 for 循环运行得更快。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-29
    • 2018-07-22
    • 1970-01-01
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多