php array_shift与array_pop执行速度差距为啥这么大

闲话不说,上问题:

一个很大的php数组(1w+),使用array_shfit跟array_pop取数组元素时,性能差距特别大,array_shift慢的无法忍受,而array_pop就很快了。

先不说答案,看段代码:

$arr = array(
    0=>123,
    3=>132,
    2=>987,
);
array_shift($arr);
//array_pop($arr);
var_dump($arr);

输出会有什么不同呢,

array_shift后,输出为:

array(2) {

[0]=>

int(132)

[1]=>

int(987)

}

array_pop后,输出为:

array(2) {

[0]=>

int(123)

[3]=>

int(132)

}

有什么不同?

对,就是array_shift操作后,数组的键值变了。这就是array_shift为什么慢的原因了。因为array_shift操作数组会对数字键值,重新从0开始重建。每次移出一个元素后,就得遍历数组中的所有元素。array_pop就不会了。一个是O(1),一个是O(n)的复杂度,数组大了之后,效果就很明显了。

php里对应函数的C代码实现:

/* {{{ void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end) */
static void _phpi_pop(INTERNAL_FUNCTION_PARAMETERS, int off_the_end)
{
	zval *stack,	/* Input stack */
		 **val;		/* Value to be popped */
	char *key = NULL;
	uint key_len = 0;
	ulong index;

	if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a", &stack) == FAILURE) {
		return;
	}

	if (zend_hash_num_elements(Z_ARRVAL_P(stack)) == 0) {
		return;
	}

	/* Get the first or last value and copy it into the return value */
	if (off_the_end) {
		zend_hash_internal_pointer_end(Z_ARRVAL_P(stack));
	} else {
		zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
	}
	zend_hash_get_current_data(Z_ARRVAL_P(stack), (void **)&val);
	RETVAL_ZVAL(*val, 1, 0);

	/* Delete the first or last value */
	zend_hash_get_current_key_ex(Z_ARRVAL_P(stack), &key, &key_len, &index, 0, NULL);
	if (key && Z_ARRVAL_P(stack) == &EG(symbol_table)) {
		zend_delete_global_variable(key, key_len - 1 TSRMLS_CC);
	} else {
		zend_hash_del_key_or_index(Z_ARRVAL_P(stack), key, key_len, index, (key) ? HASH_DEL_KEY : HASH_DEL_INDEX);
	}
//就是下面这里,遍历所有元素,对是数字键的元素重新赋值。pop的off_the_end是1,shift的off_the_end是0
	/* If we did a shift... re-index like it did before */
	if (!off_the_end) {
		unsigned int k = 0;
		int should_rehash = 0;
		Bucket *p = Z_ARRVAL_P(stack)->pListHead;
		while (p != NULL) {
			if (p->nKeyLength == 0) {//键值是数字
				if (p->h != k) {
					p->h = k++;
					should_rehash = 1;
				} else {
					k++;
				}
			}
			p = p->pListNext;
		}
		Z_ARRVAL_P(stack)->nNextFreeElement = k;
		if (should_rehash) {
		//因为重新给键赋值,hash过后的位置可能不一样了,就得重新hash后,放到对应的位置。
			zend_hash_rehash(Z_ARRVAL_P(stack));
		}
	} else if (!key_len && index >= Z_ARRVAL_P(stack)->nNextFreeElement - 1) {
		Z_ARRVAL_P(stack)->nNextFreeElement = Z_ARRVAL_P(stack)->nNextFreeElement - 1;
	}

	zend_hash_internal_pointer_reset(Z_ARRVAL_P(stack));
}
PHP_FUNCTION(array_pop)
{
	_phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
}
PHP_FUNCTION(array_shift)
{
	_phpi_pop(INTERNAL_FUNCTION_PARAM_PASSTHRU, 0);
}

php array_shift与array_pop执行速度差距为啥这么大

时间: 2024-12-30 19:54:38

php array_shift与array_pop执行速度差距为啥这么大的相关文章

【知识点整理】Oracle中NOLOGGING、APPEND、ARCHIVE和PARALLEL下,REDO、UNDO和执行速度的比较

[知识点整理]Oracle中NOLOGGING.APPEND.ARCHIVE和PARALLEL下,REDO.UNDO和执行速度的比较 1  BLOG文档结构图 2  前言部分 2.1  导读和注意事项 各位技术爱好者,看完本文后,你可以掌握如下的技能,也可以学到一些其它你所不知道的知识,~O(∩_∩)O~: ① 系统和会话级别的REDO和UNDO量的查询 ② NOLOGGING.APPEND.ARCHIVE和PARALLEL下,REDO.UNDO和执行速度的比较(重点)   Tips: ① 本文

JavaScript代码优化(下载时间和执行速度优化)

JavaScript代码的速度被分成两部分:下载时间和执行速度. 下载时间 Web浏览器下载的是js源码,因此所有长变量名和注释都回包含在内.这个因素会增加下载时间.1160是一个TCP-IP包中的字节数.最好能将每个javascript文件都保持在1160字节以下以获得最优的下载时间.    由于这个原因,要删除注释.删除制表符和空格.删除所有的换行.将长变量名缩短. 遵循这4条比较困难.因此用外部程序(ECMAScript Cruncher)来帮助我们. 要运行ESC,必使用Windows系

优化SQL的执行速度

在项目开发中,页面的反应速度是非常重要的,改善页面反应速度的方法有很多. 但一般的问题多数是出现在数据库访问的SQL上面. 比如:重复多次访问数据库,SQL速度很低等. 重复多次访问数据库需要修改逻辑来减少数据库的访问.而SQL的执行速度可以通过仔细调试解决. 下面是一些SQL的性能调试方法.整理于网络内容. 1. IN和EXISTS --1.慢   SELECT  name   FROM    Personnel   WHERE   birthday IN (SELECT  birthday 

string和stringbuffer的执行速度

如果说直接比较两者的执行速度,是不客观的,它需要在特定的情况下才能做出优劣选择: 一. 1 String str1="abc"; 2 String str2="de"; 3 String str=str1+str2 StringBuilder stringBuilder=new StringBuilder().append("abc").append("de"); 此种情况,stringbuffer更快 二. String s

解决 SqlServer执行脚本,文件过大,内存溢出问题

原文:解决 SqlServer执行脚本,文件过大,内存溢出问题 执行.sql脚本文件,如果文件较大时,执行会出现内存溢出问题,可用命令替代 cmd 中输入 osql -S 127.0.0.1,8433 -U sa -P sa -i d:\sql.sql ,-S 服务器名 -U 用户名 -P 密码 -i 文件地址,等待执行完毕即可 以上在sql2008R2下执行通过 如果数据库是 sql2008的 请将 osql 修改成为 sqlcmd 即可

同样是搭建手游app移动网站,差距怎么这么大呢

现在市面上搭建网站的系统琳琅满目,草根站长遍地都是,但是并不是每个站长的盈利差距还是相当大的.很多人就纳闷了,同样一家公司系统做出来的网站,我的网站界面并不比他们差,应用的app渠道也是相同的,不存在内容上的差别啊,为什么差距会如此之大呢?下面我们来简单分析一下. 首先,在网站的投入方面.现在的站点都运用php进行开发,但是也有很多站点通过html5进行开发.两者之间的差别当然就是在于开发的时间问题,以及用户体验度的问题上了.Html5开发的站点说难听点就是静态页面,即使你是app用户想要下载软

查看Sql语句执行速度

原文链接:http://www.cnblogs.com/New-world/archive/2012/11/28/2793560.htmlMS_SQL模糊查询like和charindex的对比 like查询效率低下,网上搜了一下替代like查询的方法,都是说用charindex方法,自己对比了一下查询速度 test1表中有一千两百多万条数据,我只给ID加了索引 先看一下 '%我%'这种模糊查询: declare @q datetime set @q = getdate() select ID,U

saiku执行速度慢

使用saiku的过程中发现一个重要问题,速度慢!下面是跟踪和优化过程 一.首先抓包,发现ajax请求:http://l-tdata2.tkt.cn6.qunar.com:8080/saiku/rest/saiku/api/query/execute 里面的参数不少,下面是截屏 二.看日志:发现了mdx语句 WITH SET [~ROWS_create_date_create_date] AS {[create_date].[create_date].[2016-04-12]} SET [~ROW

saiku执行速度优化二

上一篇文章介绍了添加filter可以加快查询速度.下面继续分析: 下面这个MDX语句: WITH SET [~FILTER] AS {[create_date].[create_date].[2013-01-01]} SET [~ROWS_dimPartner_dimPartner] AS {[dimPartner].[dimPartner].[name].Members} SET [~ROWS_sight_sight] AS Hierarchize({{[sight].[sight].[cou