好的,看看这里的其他基准测试,我对大多数开发人员似乎进行基准测试的方式摸不着头脑。
抱歉,但是这样做的方式会导致非常错误的结论,所以我必须对所提供的答案进行一些元分析。
这里的其他基准有什么问题
测量在一个永远不会改变的数组中找到元素 777 的位置,总是导致索引 117 似乎很不合适,原因很明显,我很难解释原因。您无法从这样一个过于具体的基准中合理地推断出任何东西!我能想到的唯一类比是对一个人进行人类学研究,然后将这些发现称为对这个人所居住国家的整个文化的概括概述。其他基准不是好多了。
更糟糕的是:接受的答案是一张没有指向所使用基准的链接的图像,因此我们无法控制该基准的代码是否正确(我希望 这是一个 jsperf 链接的屏幕截图,该链接最初出现在问题中,后来被编辑掉以支持新的 jsben.ch 链接)。它甚至不是对原始问题的解释:为什么一个比另一个表现更好(首先是一个备受争议的陈述)。
首先,您应该知道not all benchmarking sites are created equal - 由于它们自己的框架会干扰计时,因此某些类型的测量可能会增加重大错误。
现在,我们应该比较对数组进行线性搜索的不同方法的性能。想一想算法本身:
- 查看数组中给定索引的值。
- 将该值与另一个值进行比较。
- 如果相等,返回索引
- 如果不相等,则移动到下一个索引并比较下一个值。
这就是整个线性搜索算法,对吧?
因此,一些链接基准比较了已排序和未排序的数组(有时被错误地标记为“随机”,尽管每次迭代的顺序相同 - relevant XKCD)。很明显,这不会以任何方式影响上述算法 - 比较运算符不会看到所有值都单调增加。
是的,在将 线性搜索 与 二元 或 interpolation search 算法的性能进行比较时,有序数组与未排序数组可能很重要,但没有人就是这样!
此外,显示的所有基准测试都使用一个固定长度的数组,其中有一个固定的索引。所有这一切都告诉您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 for 循环 vs indexOf.
所以这里没有通用的答案,随着浏览器和硬件的变化,这肯定会在未来发生变化。
您甚至应该对此进行基准测试吗?
应该注意的是,在开始构建基准之前,您应该首先确定线性搜索部分是否是瓶颈!可能不是,如果是,更好的策略可能是使用不同的数据结构来存储和检索数据,和/或不同的算法。
这并不是说这个问题无关紧要——它很少见,但线性搜索性能很重要可能发生;我碰巧有一个例子:通过嵌套对象(使用字典查找)或嵌套数组(需要线性搜索)构造的prefix trie 来确定构造/搜索的速度。
As can be seen this github comment,基准测试涉及各种浏览器和平台上的各种现实和最佳/最坏情况的有效载荷。只有在经历了所有这些之后,我才能得出关于预期性能的结论。在我的情况下,对于大多数实际情况,通过数组的线性搜索比字典查找更快,但最坏情况下的性能更差到冻结脚本(并且易于构建)的程度,因此实现被标记为一种“不安全”的方法,向其他人表明他们应该考虑使用代码的上下文。
Jon J's answer 也是退一步思考真正问题的好例子。
当你做必须做微基准测试时该怎么办
所以让我们假设我们知道我们做了功课并确定我们需要优化我们的线性搜索。
那么重要的是我们期望找到元素的最终索引(如果有的话)、正在搜索的数据类型,当然还有要支持的浏览器。
换句话说:找到任何索引的可能性相同(均匀分布),还是更有可能以中间为中心(正态分布)?将在开始或接近结束时找到我们的数据?我们的值是否保证在数组中,或者只有一定百分比的时间?百分比是多少?
我是在搜索一个字符串数组吗?对象编号?如果它们是数字,它们是浮点值还是整数?我们是否正在尝试针对使用 IE10 的旧智能手机、最新笔记本电脑或学校台式机进行优化?
这是另一件重要的事情:不要针对最佳情况进行优化,而是针对现实的最坏情况性能进行优化。如果您正在构建一个 Web 应用程序,其中 10% 的客户使用非常旧的智能手机,请为此进行优化;他们的体验将是无法忍受的糟糕表现,而微优化则浪费在最新一代的旗舰手机上。
问自己这些问题,这些问题是关于您要应用线性搜索的数据以及您执行此操作的上下文。然后制作符合这些标准的测试用例,并在代表您支持的目标的浏览器/硬件上对其进行测试。