简体   繁体   English

现代浏览器中 Javascript Array.find() 的时间复杂度

[英]Time complexity of Javascript Array.find() in modern browsers

Since array.find() iterates over an array, if I handle (potentially) large arrays, I always make sure to have an indexed object like so:由于 array.find() 遍历数组,如果我处理(可能)大的 arrays,我总是确保有一个索引 object,如下所示:

{ [id:string]: Item }

if I need to look up items by id in these arrays.如果我需要在这些 arrays 中按 id 查找项目。

However, living in a time of V8 (and comparable engine optimisations for Safari and Firefox), I'm wondering if maybe under the hood, a simple array.find() is already optimized for it?但是,生活在 V8 时代(以及 Safari 和 Firefox 的类似引擎优化),我想知道是否可能在引擎盖下,一个简单的 array.find() 已经针对它进行了优化? Or will optimize for it (create such an indexed object) at runtime as soon as it has to perform this operation once?或者只要它必须执行一次此操作,就会在运行时对其进行优化(创建这样的索引对象)?

Is it true that modern browsers already have some kind of optimization for O(N) type algorithms that could become O(1) with the proper implementation?现代浏览器是否已经对 O(N) 类型的算法进行了某种优化,通过适当的实现可能变成 O(1)? Or am I thinking too much of what these browsers actually can / will do under the hood?还是我想太多这些浏览器实际上可以/将在引擎盖下做什么?

V8 developer here. V8 开发人员在这里。 The time complexity of Array.prototype.find is O(n) (with n being the array's length), and it's fair to assume that it will remain that way. Array.prototype.find的时间复杂度是 O(n)(其中 n 是数组的长度),可以公平地假设它将保持这种状态。

Generally speaking, it's often impossible for engines to improve the complexity class of an operation.一般来说,引擎通常不可能提高操作的复杂度 class 。 In case of Array.prototype.find , the predicate function you pass might well care how often it gets called:Array.prototype.find的情况下,您传递的谓词 function 可能很关心它被调用的频率:

[1, 2, 3].find((value, index, object) => {
  console.log(`Checking ${value}...`);  // Or any other side effect.
  return value === 42;
});

In such a case, the engine has no choice but to iterate over the entire array in exactly the right order, because anything else would observably break your program's behavior.在这种情况下,引擎别无选择,只能以完全正确的顺序遍历整个数组,因为其他任何事情都会明显破坏程序的行为。

In theory, since JS engines can do dynamic optimizations, they could inspect the predicate function, and if it has no side effects, they could use it to build up some sort of index/cache.理论上,由于 JS 引擎可以进行动态优化,他们可以检查谓词 function,如果没有副作用,他们可以使用它来构建某种索引/缓存。 Aside from the difficulty of building such a system that works for arbitrary predicates, this technique even when it does work would only speed up repeated searches of the same array with the same function, at the cost of wasting time and memory if this exact same scenario will not occur again.除了构建这样一个适用于任意谓词的系统的困难之外,即使它确实有效,这种技术也只会加速使用相同function 的相同数组的重复搜索,如果这种情况完全相同,则会以浪费时间和 memory 为代价不会再发生。 It seems unlikely that an engine can ever make this prediction with sufficient confidence to justify investing this time and memory.一个引擎似乎不太可能有足够的信心做出这个预测来证明这次投资和 memory 的合理性。

As a rule of thumb: when operating on large data sets, choosing efficient algorithms and data structures is worth it.根据经验:在大型数据集上操作时,选择高效的算法和数据结构是值得的。 Typically far more worth it than the micro-optimizations we're seeing so much in SO questions:-)通常比我们在 SO 问题中看到的微优化更值得:-)

A highly optimized/optimizing engine may be able to make your O(n) code somewhere between 10% and 10x as fast as it would otherwise be.一个高度优化/优化的引擎可能能够使您的 O(n) 代码速度提高 10% 到 10 倍之间。 By switching to an O(log n) or O(1) solution on your end, you can speed it up by orders of magnitude.通过切换到 O(log n) 或 O(1) 解决方案,您可以将其加速几个数量级。 That's often accomplished by doing something that engines can't possibly do.这通常是通过做一些引擎不可能做的事情来完成的。 For example, you can keep your array sorted and then use binary search over it -- that's something an engine can't do for you automatically because obviously it's not allowed to reorder your array's contents without your approval.例如,您可以保持数组排序,然后对其使用二进制搜索——这是引擎无法自动为您做的事情,因为显然未经您的批准不允许对数组的内容进行重新排序。 And as @myf already points out in a comment: if you want to access things by a unique key, then using a Map will probably work better than using an Array .正如@myf 已经在评论中指出的那样:如果您想通过唯一键访问事物,那么使用Map可能比使用Array更好。

That said, simple solutions tend to scale better than we intuitively assume;也就是说,简单的解决方案往往比我们直观地假设的更容易扩展; the standard warning against premature optimizations applies here just as everywhere else.针对过早优化的标准警告在这里适用于其他任何地方。 Linearly searching through arrays is often just fine, you don't need a (hash) map just because you have more than three items in it.通过 arrays 线性搜索通常就可以了,您不需要(散列)map 仅仅因为其中包含三个以上的项目。 When in doubt, profile your app to find out where the performance bottlenecks are.如有疑问,请分析您的应用程序以找出性能瓶颈所在。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM