PHP:array_key_exists的搜索速度比in_array快500倍

在2014年,他们已经撰写了有关数组搜索的文章,但几乎没人知道。

从那时起,已经发布了许多版本的PHP,但尚未修复,这意味着反馈很差,很少有人知道。在python上是相同的,在3 *中比在2.7中差。

有时您需要在一个字符串数组中找到一个字符串 -在不同算法中非常频繁的操作,并且如果数组很小并且看上去有点而不是处于循环中,则in_array是正常的,它不会影响整体速度,但是如果您需要大数据并查找十亿行和十亿次的数组,那么这很关键:更好的时间,而不是每周。

一个简单的测试显示:

in_array在6-9秒内查找 ideone.com/Yb1mDa 6600ms
,array_key_exists查找相同的东西,但比250(php5.6 / py3。*)快400倍以上(php7.3 / py2.7) ideone .com / gwSmFc(周期增加了100倍)12ms(6600/12 = 550倍+加载和缓存导致的-10%扩展)

为什么会发生这种情况?详细考虑:

1)在纯汇编程序中查找字符串是对字符串数组(快速或冒泡)进行排序,然后进行二进制搜索。

二进制搜索日志中的步数(n)次取决于数组的大小,并且比简单搜索小得多。

您可以一次对字符串数组进行一次排序,然后进行缓存,然后进行十亿次搜索。但这无济于事。

默认情况下,排序会再次发生,尽管他们写道,它们通过散列在7.2 in_array中得到了改善,但并没有太大改善。

2)在关联中搜索索引/关键字(作为字符串)。数组/字典通过字符串哈希和冲突处理发生(哈希搜索错误)。哈希是数组的数字索引,并通过2个步骤从数组中获取数字索引(零元素的地址)+ offset *带有此哈希的字符串数组的指针的大小。 +蛮力碰撞,平均步伐比二进制搜索少。
创建字典元素$ m [key] = val时,索引哈希将自动自动进行一次并被缓存。

散列的大小,散列算法已缝制到PCP引擎中,并且无法更改,尽管源代码是开放的,但您可以下载更改并编译服务器。

您无法继续阅读,只需将in_array更改为array_combine + array_key_exists。

通过散列搜索时的步骤数取决于冲突数和具有相同散列的行数。它们需要进行排序,或者也需要进行排序和二进制搜索。

为了减少冲突,可以分配更多的内存,如果现在不再像50年前那样问题了,当时电磁线圈上的1 kb内存像飞机一样花费很大。那时所有的基本算法都被发明出来了:sort / zip / gif / jpg /等-它们不需要很多内存,但是它们很糟糕,现在它们要好得多,但是它们需要1-16 MB的大量内存。是的,有些服务器具有256 MB的服务器,每个服务器都有一个单独的流,而16 MB已经足够了,但是在普通用户的设备上至少1 GB,而16 MB的存储桶中却有一个小数目。

如果将调用array_key_exists函数的调用替换为isset($ m [key])构造,您将获得更大的效果,它不会清除命令队列和缓存,不使用堆栈,并且速度提高了大约20%。

如果您创建前两个字母的数组-4 * 16kb,并首先在偏移量(索引=第一个字符的代码+ 2nd * 256)处查找指向字符串其余部分的哈希数组的指针,然后查找一个由字符串组成的小数组,则可以加快处理速度碰撞要小得多。

它需要更多的内存,算法也更复杂,但是搜索速度要快30倍以上。但这不是用php实现的,您可以编写so / dll库并调用它,或者要求开发人员在7.5中添加它。

您可以通过mySQL搜索,但是您需要对查询进行分组,但它仍然会比较慢。

PS:这种方法是我在加速一个大型慢速网站时通过键入,直觉和经验偶然发现的,其中有很多这样的技巧和窍门,我设法将数据从40秒导出到0.8秒,并使用排序和过滤器输出列表,还有很多其他尽管标准技术,框架和框架很方便并且可以加快开发速度,但是它们做起来太慢了。

All Articles