Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/opencv/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Php 在foreach循环参数内分解数组_Php_Performance_Foreach - Fatal编程技术网

Php 在foreach循环参数内分解数组

Php 在foreach循环参数内分解数组,php,performance,foreach,Php,Performance,Foreach,vs 在第一个示例中,它是将每次迭代的字符串分解为$foo还是PHP将其保存在内存中,并在其自己的临时变量中分解?从效率的角度来看,创建额外的变量$test有意义吗?或者两者几乎相等?什么意义上的效率?内存管理,还是处理器?处理器不会对内存产生影响-您始终可以执行$foo=explode(',',$foo)在第一种情况下,PHP将其分解一次并保存在内存中 创建不同变量或以其他方式产生的影响可以忽略不计。PHP解释器将需要维护一个指向下一项位置的指针,无论它们是否是用户定义的。从内存的角度来看,这

vs


在第一个示例中,它是将每次迭代的
字符串分解为
$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);}