如何在PHP中优化此函数的内存使用?

如何在PHP中优化此函数的内存使用?,php,memory-management,memory-leaks,out-of-memory,Php,Memory Management,Memory Leaks,Out Of Memory,此函数传递大约70k个对象以进行处理。加载数组没有问题,在失败之前,它完成了大约一半的迭代。内存限制为ini_集('Memory_limit','465M')(云服务)。在$googleFunction:/app/vendor/googleads/googleads php lib/src/Google/Api/Ads/Common/lib/AdsSoapClient.php 我已经尝试过将数组作为引用传递,从array\u chunk切换到一次使用array\u slice,通过引用$goog

此函数传递大约70k个对象以进行处理。加载数组没有问题,在失败之前,它完成了大约一半的迭代。内存限制为
ini_集('Memory_limit','465M')(云服务)。在
$googleFunction
/app/vendor/googleads/googleads php lib/src/Google/Api/Ads/Common/lib/AdsSoapClient.php

我已经尝试过将数组作为引用传递,从
array\u chunk
切换到一次使用
array\u slice
,通过引用
$googleFunction
传递
$chunk
,在最后取消
$chunk
,并在每次迭代后调用
gc\u collect\u cycles()

它怎么还能失败呢?某个地方一定有内存泄漏,但除了
$chunk
$result
之外,没有大的赋值,并且在每次迭代期间调用的每个函数都超出范围,因此它可能分配的任何内容都应该被垃圾收集。我觉得这可能与函数引用有关。经过大约四分之一的迭代,它使用了240M。每一次迭代大约会增加10万次

  function googleJob($job = null, &$list, $googleFunction, $before = null) {
    // initialize $total, $gaw, $processed
    for ($chunkIndex = 0; $chunkIndex < count($list); $chunkIndex += 2000) { 
      echo '3:'.memory_get_usage().' ';
      $chunk = array_slice($list, $chunkIndex, 2000); # limit of 2000/request
      echo '4:'.memory_get_usage().' ';
      if ($before) {
        foreach ($chunk as $item) {
          $before($item); # function reference 
        }
      }
      echo '5:'.memory_get_usage().' ';

      $i = 0; // try harder to make Google work
      $result = null;
      do {
        try {
          $result = $gaw->$googleFunction($chunk);
          echo '6:'.memory_get_usage().' ';
        } catch (\SoapFault $e) { # try to remove the bad items and try again
          // no errors generated
        }
      } while ($result == null && $chunk); // Retry the request if not empty

      array_walk($chunk, function($item) { $item->save(); });
      echo '7:'.memory_get_usage().' ';
      $processed += count($chunk);
      if ($job) {
        $job->progress = round($processed / $total * 100);
        $job->save() or Yii::error($job->getErrors());
      }
      echo '8:'.memory_get_usage().' ';      
      unset($chunk);
      unset($result);
      echo '9:'.memory_get_usage().'... ';
      gc_collect_cycles();
      echo memory_get_usage().PHP_EOL;
    }
  }

在我看来,你们在滥用soap服务。如果你告诉我们你的代码在$googleFunction失败,我可以为你提供设置$chunk的100或200个对象

第二件事是$item->save()函数。如果您有权访问该类,则应检查是否存在HAS-IS类。内存中唯一的地方是这样的结构:

class Foo {
    function __construct()
    {
        $this->bar = new Bar($this);
    }
}

class Bar {
    function __construct($foo = null)
    {
        $this->foo = $foo;
    }
}



for($i = 0; $i < 10; $i++){

     $foo = new Foo();
     unset($foo);
     echo number_format(memory_get_usage()) . "<br>";

} 

这应该有帮助

在这里可能相关,也可能无关,但详细描述了垃圾收集的作用。我从未有幸告诉PHP如何管理内存。它并不是真正设计的。您可能想考虑使用队列来处理这些作业。将代码< >清单> /代码>作为参考是没有意义的,因为您从不修改该数组。<代码> $item > SAVER()<代码>?这似乎是函数中唯一会占用大量内存的部分,因为它将每个输入项都保存在某个位置。此外,
$gaw->$googleFunction
是否将
$chunk
保存到任何位置?),最多支持5000个。但我会一次尝试100次,并使用循环引用测试泄漏。好的,即使是较小的200块,它仍然会泄漏。有趣的是,
$save()
实际上会泄漏内存
foreach($agk as$v){$v->save();echo memory\u get\u usage().PHP\u EOL;}
class Foo {
    function __construct()
    {
        $this->bar = new Bar($this);
    }
}

class Bar {
    function __construct($foo = null)
    {
        $this->foo = $foo;
    }
}



for($i = 0; $i < 10; $i++){

     $foo = new Foo();
     unset($foo);
     echo number_format(memory_get_usage()) . "<br>";

} 
function __destruct()
    {
        unset($this->bar);
    }