Php 在foreach循环参数内分解数组
vsPhp 在foreach循环参数内分解数组,php,performance,foreach,Php,Performance,Foreach,vs 在第一个示例中,它是将每次迭代的字符串分解为$foo还是PHP将其保存在内存中,并在其自己的临时变量中分解?从效率的角度来看,创建额外的变量$test有意义吗?或者两者几乎相等?什么意义上的效率?内存管理,还是处理器?处理器不会对内存产生影响-您始终可以执行$foo=explode(',',$foo)在第一种情况下,PHP将其分解一次并保存在内存中 创建不同变量或以其他方式产生的影响可以忽略不计。PHP解释器将需要维护一个指向下一项位置的指针,无论它们是否是用户定义的。从内存的角度来看,这
在第一个示例中,它是将每次迭代的
字符串分解为$foo
还是PHP将其保存在内存中,并在其自己的临时变量中分解?从效率的角度来看,创建额外的变量$test
有意义吗?或者两者几乎相等?什么意义上的效率?内存管理,还是处理器?处理器不会对内存产生影响-您始终可以执行$foo=explode(',',$foo)
在第一种情况下,PHP将其分解一次并保存在内存中
创建不同变量或以其他方式产生的影响可以忽略不计。PHP解释器将需要维护一个指向下一项位置的指针,无论它们是否是用户定义的。从内存的角度来看,这不会有什么区别,因为PHP使用了
除此之外,我个人会选择第一个选项——这是一个少行但可读性不差的选项(imho!)。我可以做出一个有根据的猜测,但让我们试试看
我想有三种主要的方法来解决这个问题
进入循环前分解并指定
在循环内分解,无赋值
字符串标记化
我的假设:
由于分配,可能会消耗更多内存
可能与#1或#3相同,不确定是哪个
可能更快、更小的内存占用
方法
以下是我的测试脚本:
$test = explode(',' $foo);
foreach($test as $bar) { ... }
(二)
(三)
结果
结论
看起来有些假设被推翻了。你不喜欢科学吗?:-)
- 总的来说,这些方法中的任何一种对于“合理大小”(几百或几千)的列表都足够快
- 如果你在迭代一些非常大的东西,时间差相对较小,但是内存使用量可能会相差一个数量级李>
- 当您
explode()
inline而不进行预分配时,由于某些原因,它会稍微慢一点
- 令人惊讶的是,标记化比显式迭代声明的数组要慢一些。在如此小的规模上工作,我相信这是由于每次迭代都要调用
strtok()
函数的调用堆栈开销造成的。下面将对此进行详细介绍
就函数调用的数量而言,explode()。O(1)对O(n)
我在循环中使用函数调用运行方法1)的图表中添加了一项额外功能。我使用了strlen($val)
,认为这将是一个相对类似的执行时间。这是一个有争议的话题,但我只是想提出一个一般性的观点。(我只运行了strlen($val)
,忽略了它的输出。我没有将它分配给任何东西,因为分配会增加时间成本。)
从结果表中可以看出,它随后成为三种方法中速度最慢的方法
最后的想法
了解这一点很有趣,但我的建议是做您认为最可读/可维护的事情。只有当你真的要处理一个非常大的数据集时,你才应该担心这些微优化。@Ryan:Ooops,我是说第一个;)@谢谢,这是一个控制结构。。。;foreach($x将在循环后使用比
foreach更多的内存(…
。仅仅因为$x
变量在后记中仍然保持不变。但这并不重要。变量将在返回时被销毁
,或者,如果内存很关键,可以取消设置
。有趣的是内存使用的峰值,因为这只关系到内存的限制。在这里我非常高兴相信它将为两种foreach变体提供非常相似的结果。记住:如果您是“基准测试”您通常希望使用的内存内存\u get\u peak\u usage
,而不是……内存\u get\u usage
。内存中的#2和#3是相同的,这也是因为您只是在循环后测量内存使用情况。strok的峰值内存可能会更小。这与PHP转换无关循环中的分解为标记化。关于最后一个示例:函数调用在PHP中很昂贵;)您strlen($val);
将涉及执行五个操作码。谢谢,对于这些结果,还必须提及版本和操作系统。
$test = explode(',' $foo);
foreach($test as $bar) { ... }
<?php
ini_set('memory_limit', '1024M');
$listStr = 'text';
$listStr .= str_repeat(',text', 9999999);
$timeStart = microtime(true);
/*****
* {INSERT LOOP HERE}
*/
$timeEnd = microtime(true);
$timeElapsed = $timeEnd - $timeStart;
printf("Memory used: %s kB\n", memory_get_peak_usage()/1024);
printf("Total time: %s s\n", $timeElapsed);
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {}
// explode inline-ly
foreach (explode(',', $listStr) as $val) {}
// tokenize
$tok = strtok($listStr, ',');
while ($tok = strtok(',')) {}
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {strlen($val);}