首页 > 开发 > Php > 正文

PHP中array_keys和array_unique函数源码的分析

2020-02-21 20:43:44
字体:
来源:转载
供稿:网友

性能分析

从运行性能上分析,看看下面的测试代码:

$test=array();for($run=0; $run<10000; $run++)$test[]=rand(0,100);$time=microtime(true);$out = array_unique($test);$time=microtime(true)-$time;echo 'Array Unique: '.$time."/n";$time=microtime(true);$out=array_keys(array_flip($test));$time=microtime(true)-$time;echo 'Keys Flip: '.$time."/n";$time=microtime(true);$out=array_flip(array_flip($test));$time=microtime(true)-$time;echo 'Flip Flip: '.$time."/n";

运行结果如下:

从上图可以看到,使用array_unique函数需要0.069s;使用array_flip后再使用array_keys函数需要0.00152s;使用两次array_flip函数需要0.00146s。

测试结果表明,使用array_flip后再调用array_keys函数比array_unique函数快。那么,具体原因是什么呢?让我们看看在PHP底层,这两个函数是怎么实现的。

源码分析

/* {{{ proto array array_keys(array input [, mixed search_value[, bool strict]])  Return just the keys from the input array, optionally only for the specified       search_value */PHP_FUNCTION(array_keys){  //变量定义  zval *input,        /* Input array */     *search_value = NULL,  /* Value to search for */     **entry,        /* An entry in the input array */      res,          /* Result of comparison */     *new_val;        /* New value */  int  add_key;        /* Flag to indicate whether a key should be added */  char *string_key;      /* String key */  uint  string_key_len;  ulong num_key;        /* Numeric key */  zend_bool strict = 0;    /* do strict comparison */  HashPosition pos;  int (*is_equal_func)(zval *, zval *, zval * TSRMLS_DC) = is_equal_function;  //程序解析参数  if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a|zb", &input, &search_value, &strict) == FAILURE) {    return;  }  // 如果strict是true,则设置is_equal_func为is_identical_function,即全等比较  if (strict) {    is_equal_func = is_identical_function;  }  /* 根据search_vale初始化返回的数组大小 */  if (search_value != NULL) {    array_init(return_value);  } else {    array_init_size(return_value, zend_hash_num_elements(Z_ARRVAL_P(input)));  }  add_key = 1;  /* 遍历输入的数组参数,然后添加键值到返回的数组 */  zend_hash_internal_pointer_reset_ex(Z_ARRVAL_P(input), &pos);//重置指针  //循环遍历数组  while (zend_hash_get_current_data_ex(Z_ARRVAL_P(input), (void **)&entry, &pos) == SUCCESS) {    // 如果search_value不为空    if (search_value != NULL) {      // 判断search_value与当前的值是否相同,并将比较结果保存到add_key变量      is_equal_func(&res, search_value, *entry TSRMLS_CC);      add_key = zval_is_true(&res);    }    if (add_key) {      // 创建一个zval结构体      MAKE_STD_ZVAL(new_val);      // 根据键值是字符串还是整型数字将值插入到return_value中      switch (zend_hash_get_current_key_ex(Z_ARRVAL_P(input), &string_key, &string_key_len, &num_key, 1, &pos)) {        case HASH_KEY_IS_STRING:          ZVAL_STRINGL(new_val, string_key, string_key_len - 1, 0);          // 此函数负责将值插入到return_value中,如果键值已存在,则使用新值更新对应的值,否则直接插入          zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);          break;        case HASH_KEY_IS_LONG:          Z_TYPE_P(new_val) = IS_LONG;          Z_LVAL_P(new_val) = num_key;          zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &new_val, sizeof(zval *), NULL);          break;      }    }    // 移动到下一个    zend_hash_move_forward_ex(Z_ARRVAL_P(input), &pos);  }}/* }}} */            
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表