foreach(explode(',' $foo) as $bar) { ... }
VS
$test = explode(',' $foo);
foreach($test as $bar) { ... }
在第一个示例中,每次迭代是explode
$foo
字符串还是PHP将其保存在内存中,并在其自己的临时变量中爆炸?从效率的角度来看,创建额外变量$test
或两者都非常相等是否有意义?
答案 0 :(得分:22)
我可以做出有根据的猜测,但让我们尝试一下!
我认为有三种主要方法可以解决这个问题。
我的假设:
这是我的测试脚本:
<?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);
以下是三个版本:
1)
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {}
2)
// explode inline-ly
foreach (explode(',', $listStr) as $val) {}
3)
// tokenize
$tok = strtok($listStr, ',');
while ($tok = strtok(',')) {}
看起来有些假设被证明是错误的。你不爱科学吗? : - )
explode()
内联而没有预先分配时,由于某种原因它会慢一点。strtok()
的调用堆栈开销。更多内容如下。就函数调用的数量而言,explode()
确实是顶级标记化。 O(1) vs O(n)
我在图表中添加了奖励,我在循环中使用函数调用运行方法1)。我使用strlen($val)
,认为这是一个相对类似的执行时间。这是有争议的,但我只是想提出一个普遍的观点。 (我只运行了strlen($val)
并忽略了它的输出。我做了不将它分配给任何东西,因为分配将是额外的时间成本。)
// explode separately
$arr = explode(',', $listStr);
foreach ($arr as $val) {strlen($val);}
从结果表中可以看出,它成为三者中最慢的方法。
这很有趣,但我的建议是做任何你认为最易读/可维护的事情。只有当你真正处理一个非常大的数据集时,你才会担心这些微观优化。
答案 1 :(得分:6)
在第一种情况下,PHP会将其爆炸一次并将其保留在内存中。
创建不同变量或其他方式的影响可以忽略不计。无论用户是否定义,PHP解释器都需要维护指向下一个项目位置的指针。
答案 2 :(得分:3)
从内存的角度来看,它没有什么区别,因为PHP使用copy on write concept。
除此之外,我个人会选择第一个选项 - 它是一条线,但不是那么可读(imho!)。
答案 3 :(得分:1)
效率在什么意义上?内存管理还是处理器?对于内存而言,处理器不会产生任何影响 - 您始终可以执行$foo = explode(',', $foo)