gpt4 book ai didi

php - 在 foreach 循环参数中分解数组

转载 作者:可可西里 更新时间:2023-10-31 22:18:36 24 4
gpt4 key购买 nike

foreach(explode(',' $foo) as $bar) { ... }

对比

$test = explode(',' $foo);
foreach($test as $bar) { ... }

在第一个例子中,它是在每次迭代中explode $foo 字符串,还是 PHP 将它保存在内存中并在它自己的临时变量中展开?从效率的角度来看,创建额外的变量 $test 是否有意义,或者两者几乎相等?

最佳答案

我可以做出有根据的猜测,但让我们试试看!

我认为可以通过三种主要方法来解决这个问题。

  1. 进入循环前分解赋值
  2. 在循环内爆炸,不赋值
  3. 字符串分词

我的假设:

  1. 可能由于分配而消耗更多内存
  2. 可能与#1 或#3 相同,不确定是哪个
  3. 可能既更快又占用更少的内存

方法

这是我的测试脚本:

<?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() benchmark results

结论

看起来有些假设被覆盖了。你不爱科学吗? :-)

  • 总的来说,对于“合理大小”(几百或几千)的列表,这些方法中的任何一种都足够快。
  • 如果您要遍历巨大的东西,时间差异相对较小,但内存使用量可能相差一个数量级!
  • 当您explode() 在没有预分配的情况下内联时,由于某些原因它会慢一些。
  • 令人惊讶的是,标记化比显式迭代声明的数组。在如此小的规模上工作,我认为这是由于每次迭代都对 strtok() 进行函数调用的调用堆栈开销所致。更多内容请见下文。

就函数调用的数量而言,explode()ing 确实名列前茅。 O(1)O(n)

我在运行方法 1) 的图表中添加了一个额外的功能,并在循环中调用了一个函数。我用的是strlen($val),以为会是比较相似的执行时间。这是有争议的,但我只是想提出一个一般性的观点。 (我只运行了 strlen($val) 并忽略了它的输出。我没有将它分配给任何东西,因为分配将是额外的时间成本。)

// explode separately 
$arr = explode(',', $listStr);
foreach ($arr as $val) {strlen($val);}

从结果表中可以看出,它成为三种方法中最慢的一种。

最后的想法

这很有趣,但我的建议是做任何您认为最易读/可维护的事情。只有当您真正处理的是一个非常大的数据集时,您才应该担心这些微优化。

关于php - 在 foreach 循环参数中分解数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5861826/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com