对于大数组查找某个值in_array和array_flip+isset的性能比较
- 6338
- PHP
- 10
- super_dodo
- 2016/09/21
假设有一个10万条记录的数组,需要查找某一个值是否存在该数组内.大多数情况下直接使用in_array这个PHP的自带函数,但是当这个数组很大和很复杂的时候,建议使用array_flip和isset的方式来提高性能.
首先来看一下PHP源码,从代码中可以看出while循环在遍历数组中的所有元素取值做对比,如果数组中元素特别多又频繁调用的时候,效率可想而知。
由于数组的键是放在Hash表的key中的,Hash遍历会根据键的哈希值去查找,效率非常高,所以尝试了一上array_flip将键值对换,然后用isset去判断,效率呈指数级提高。
//得到毫秒的方法
function getMillisecond() {
list($t1, $t2) = explode(' ', microtime());
return (float)sprintf('%.0f',(floatval($t1)+floatval($t2))*1000);
}
//构建一个10万条自增的新数组
$array = [];
for ($i = 0; $i < 100000; $i++) {
$array[] = $i;
}
//直接使用in_array的方法去循环执行10万次查找
$start_time = getMillisecond();
for ($i = 0; $i < 100000; $i++) {
$k = rand(0,100000);
if(in_array($k,$array)){
echo $k;
}
}
echo '使用in_array占用时间:', (getMillisecond() - $start_time) . "毫秒
";
//反转键和值array_flip
$start_time = getMillisecond();
$array_flip = array_flip($array);
for ($i = 0; $i < 100000; $i++) {
$k = rand(0,100000);
if(isset($array_flip[$k])){
echo $k;
}
}
echo '使用isset占用时间:', (getMillisecond() - $start_time) . "毫秒";
//输出结果
//使用in_array占用时间:6336毫秒
//使用isset占用时间:121毫秒
//使用in_array占用时间:6347毫秒
//使用isset占用时间:362毫秒
//使用in_array占用时间:6374毫秒
//使用isset占用时间:161毫秒
//对于10万条数据执行10万次的效率来说,结果令人吃惊,所以建议在做统计等密集运算的时候,尽量不要使用in_array函数!
[/php]
附上PHP的in_array的源码,来源于网络,经供参考.
[php]
/* void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior)
* 0 = return boolean
* 1 = return key
*/
static void php_search_array(INTERNAL_FUNCTION_PARAMETERS, int behavior) /* {{{ */
{
zval *value, /* value to check for */
*array, /* array to check in */
**entry, /* pointer to array entry */
res; /* comparison result */
HashPosition pos; /* hash iterator */
zend_bool strict = 0; /* strict comparison or not */
int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "za|b", &value, &array, &strict) == FAILURE) {
return;
}
if (strict) {
is_equal_func = is_identical_function;
}
zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(array), &pos);
while (zend_hash_get_current_data_ex(Z_ARRVAL_P(array), (void **)&entry, &pos) == SUCCESS) {
is_equal_func(&res, value, *entry TSRMLS_CC);
if (Z_LVAL(res)) {
if (behavior == 0) {
RETURN_TRUE;
} else {
zend_hash_get_current_key_zval_ex(Z_ARRVAL_P(array), return_value, &pos);
return;
}
}
zend_hash_move_forward_ex(Z_ARRVAL_P(array), &pos);
}
RETURN_FALSE;
}
/* }}} */
[/php]
相关阅读
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
热门文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例
最新文章
- 通过Google API客户端访问Google Play帐户报告PHP库
- PHP执行文件的压缩和解压缩方法
- 消息中间件MQ与RabbitMQ面试题
- 如何搭建一个拖垮公司的技术架构?
- Yii2中ElasticSearch的使用示例