好的,看到其他基准测试结果,我对大多数开发人员进行基准测试的方式感到困惑。
抱歉,但是这种做法会导致极其错误的结论,因此我必须进行一些元分析并对提供的答案进行评论。
这里其他基准测试的问题
测量在永远不变的数组中查找元素777的位置,始终导致索引117似乎非常不合适,我很难解释为什么。您无法从这样一个过度特定的基准测试中合理地推断任何内容!我能想到的唯一类比是对一个人进行人类学研究,然后将发现称为该人所居住国家的整个文化的概述。其他基准测试也不太好。
更糟糕的是:接受的答案是一个没有链接到使用的基准测试的图像,因此我们无法控制该基准测试的代码是否正确(我希望它是原本在问题中的jsperf链接的截图,并在新的jsben.ch链接中进行了编辑)。这甚至不是原始问题的解释:为什么一个比另一个表现更好(这本身就是一个高度可争议的陈述)。
首先,您应该知道并非所有基准测试网站都是平等的-一些网站可能会由于其自身框架干扰计时而对某些类型的测量增加显着误差。
现在,我们应该比较不同的线性搜索数组方法的性能。先思考一下算法本身:
- 查看数组中给定索引处的值。
- 将该值与另一个值进行比较。
- 如果相等,则返回索引。
- 如果不相等,则移动到下一个索引并比较下一个值。
这就是整个线性搜索算法,对吧?
因此,一些链接的基准测试比较已排序和未排序的数组(有时错误地标记为“随机”,尽管每次迭代顺序相同 -
相关XKCD)。显然,这不会以任何方式影响上述算法 - 比较运算符不会看到所有值都单调递增。
是的,在将线性搜索与二进制或
插值搜索算法的性能进行比较时,有序与无序的数组可能会有所影响,但这里没有人这样做!
此外,所有显示的基准测试都使用固定长度的数组,并且具有固定的索引。这只告诉您
indexOf
在该确切长度的确切索引中找到的速度有多快 - 如上所述,您不能从中概括任何内容。
以下是将问题中链接的基准测试复制到perf.zone(比jsben.ch更可靠)的结果,但进行了以下修改:
- 每次运行时,我们随机选择数组的一个值,这意味着我们假设每个元素被选中的概率相等
- 我们对100个和1000个元素进行基准测试
- 我们比较整数和短字符串。
https://run.perf.zone/view/for-vs-while-vs-indexof-100-integers-1516292563568
https://run.perf.zone/view/for-vs-while-vs-indexof-1000-integers-1516292665740
https://run.perf.zone/view/for-vs-while-vs-indexof-100-strings-1516297821385
https://run.perf.zone/view/for-vs-while-vs-indexof-1000-strings-1516293164213
这是我机器上的结果:
https://imgur.com/a/fBWD9
正如您所看到的,结果会根据使用的基准和浏览器而发生 drastical 变化,并且每个选项在至少一个方案中都获胜:缓存长度 vs 未缓存长度,while 循环 vs for 循环 vs indexOf。
因此,在这里没有通用答案,并且随着浏览器和硬件的更改,这肯定会在将来发生变化。
你甚至应该对此进行基准测试吗?
应该注意的是,在您继续构建基准测试之前,您应确定线性搜索部分是否首先成为瓶颈!它可能并不是,如果是,更好的策略可能是使用不同的数据结构来存储和检索数据,或者使用不同的算法。
这并不是说这个问题是不相关的 - 这很少见,但线性搜索性能很重要;我碰巧有一个例子:通过嵌套对象(使用字典查找)或嵌套数组(需要线性搜索)建立速度
prefix trie 的构造/搜索。
如
可以在此Github评论中看到, 基准测试涉及各种浏览器和平台上的各种现实和最佳/最坏情况的负载。只有经过所有这些才能得出关于预期性能的结论。在我看来,对于大多数现实情况,通过数组进行线性搜索比查找字典更快,但最坏情况的性能更差,甚至会导致脚本冻结(并且易于构建),因此将其标记为“不安全”方法以向其他人发出信号,让他们考虑代码将被使用的上下文。
Jon J's answer也是一个很好的例子,可以退一步思考真正的问题。
当您必须进行微基准测试时该怎么办
所以让我们假设我们知道我们已经做好了功课,并确定我们需要优化我们的线性搜索。
那么重要的是我们期望找到元素的最终索引(如果有的话),正在搜索的数据类型以及支持哪些浏览器。
换句话说:任何索引都同样可能被找到(均匀分布),还是更有可能集中在中间(正态分布)?我们会在开头或接近结尾处找到数据吗?我们的值是否保证在数组中,还是只有一定百分比的时间?百分之几?
我正在搜索一个字符串数组吗?对象数字?如果它们是数字,它们是浮点值还是整数?我们正在尝试优化较旧的智能手机、最新的笔记本电脑还是卡在IE10的学校台式机?
这是另一个重要的事情:不要优化最佳性能,而是优化现实中的最坏性能。如果您正在构建一个Web应用程序,其中10%的客户使用非常老旧的智能手机,请针对此进行优化;他们的体验将是无法忍受的糟糕性能,而微小的优化则浪费在最新一代旗舰手机上。
针对您应用线性搜索的数据以及您所处的上下文,自问以下问题。然后制定符合这些标准的测试用例,并在代表您支持的目标的浏览器/硬件上进行测试。