好吧,看看这里的其他基准测试,我对大多数开发人员似乎进行基准测试的方式感到头疼。
抱歉,但这样做的方式会导致非常错误的结论,所以我必须稍微有点元,并对所提供的答案发表评论。
这里的其他基准有什么问题
测量在一个永远不会改变的数组中找到元素 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
如您所见,结果会因基准测试和所使用的浏览器而发生巨大变化,并且每个选项至少在以下一种情况下获胜:缓存长度 vs 未缓存长度,while 循环 vs for 循环 vs indexOf
.
所以这里没有统一的答案,而且随着浏览器和硬件的变化,这肯定会在未来发生变化。
你甚至应该对此进行基准测试吗?
应该注意的是,在开始构建基准之前,您应该确定线性搜索部分是否是一个瓶颈!它可能不是,如果是,更好的策略可能是使用不同的数据结构来存储和检索数据,和/或不同的算法。
那是不是说,这个问题是不相关的-它是罕见的,但它可以发生线性搜索性能事项; 我碰巧有一个例子:通过通过嵌套对象(使用字典查找)或嵌套数组(需要线性搜索)构造的前缀树来建立构造/搜索的速度。
从这个 github 评论可以看出,基准测试涉及各种浏览器和平台上的各种现实和最佳/最坏情况的有效载荷。只有在经历了所有这些之后,我才能得出关于预期性能的结论。就我而言,对于大多数实际情况,通过数组的线性搜索比字典查找要快,但最坏情况下的性能更差到冻结脚本的程度(并且易于构建),因此实现被标记为一种“不安全”的方法,向其他人发出信号,告诉他们应该考虑使用代码的上下文。
Jon J 的回答也是退一步思考真正问题的一个很好的例子。
当您必须进行微基准测试时该怎么办
所以让我们假设我们知道我们做了功课并确定我们需要优化我们的线性搜索。
那么重要的是我们期望找到元素的最终索引(如果有的话),正在搜索的数据类型,当然还有要支持的浏览器。
换句话说:找到任何指数的可能性是否相等(均匀分布),还是更有可能以中间为中心(正态分布)?会在开始还是接近结束时找到我们的数据?我们的值是保证在数组中,还是只在一定百分比的时间内?什么百分比?
我在搜索字符串数组吗?对象编号?如果它们是数字,它们是浮点值还是整数?我们是否试图针对旧智能手机、最新笔记本电脑或使用 IE10 的学校台式机进行优化?
这是另一件重要的事情:不要针对最佳情况进行优化,而是针对实际的最坏情况进行优化。如果您正在构建一个 Web 应用程序,其中 10% 的客户使用非常旧的智能手机,请为此进行优化;他们的体验将是性能不佳的体验,而微优化则浪费在最新一代的旗舰手机上。
问问自己这些关于您应用线性搜索的数据的问题,以及您在其中进行搜索的上下文。然后制作适合这些标准的测试用例,并在代表您支持的目标的浏览器/硬件上测试它们。