【问题标题】:Garbage collection / reduce memory usage垃圾收集/减少内存使用
【发布时间】:2021-04-30 18:15:15
【问题描述】:

如果我的代码看起来像这样(这里是 Laravel 代码,但它应该普遍适用):

class SomeClass 
{
    public function doSomething(array $data)
    {
        foreach ($data as $item) {
            $this->doSomethingWithItem($item);
        }
    }

    private function doSomethingWithItem($item)
    {
        $model = SomeModel::make($item);

        // ... some other stuff 

        $model->save();
    }
}

所以我的问题是,如果$data 是一个非常大的集合(在我的实际实现中它是一个生成器),内存使用量会随着数据项的数量线性增加。

既然$model 是一个局部变量并且只被引用,那么它不应该被垃圾收集吗?我什至在最后尝试了unset($model) 来强制释放它,但它没有效果。

如何在不增加内存使用量的情况下使用这种模式?由于我没有存储任何数据结构,内存使用量不应该随着每次迭代而增加吗?

我错过了什么吗?

【问题讨论】:

标签: php laravel memory garbage-collection out-of-memory


【解决方案1】:

IIRC unset() 不会强制 GC,它只是删除引用。你可以拨打gc_collect_cycles()强制。

旁注: 另一种方法是将数据分块,这也允许数据集大于内存。

编辑: 再次阅读后,您只是想摆脱数据的“包装器”(模型)。数据仍然存在于内存中,因为$item 是实际占用内存的内容,并且永远不会被销毁并且存在于doSomething() 的范围内。

【讨论】:

  • 这段代码是一个简化。 $item 是一个数组,我想根据来自$item 的数据创建SomeModel 的行。我不想将它包装在模型中。 $item 不负责内存增加。如果我在doSomethingWithItem() 的开头放置return 语句,则内存使用率将保持在较低水平,并且$item 仍处于分配状态。
  • 我不知道您的SomeModel 类添加了哪些额外数据,但如果您真的认为这仍然是问题,请致电unset($model);gc_collect_cycles(); 这将导致每次调用时 gc 都会运行但是,它可能会显着减慢。不过,您可以输入一个标志,使其每 x 次运行一次。
猜你喜欢
  • 2017-08-06
  • 1970-01-01
  • 1970-01-01
  • 2021-12-28
  • 1970-01-01
  • 1970-01-01
  • 2011-06-18
  • 2017-03-15
  • 1970-01-01
相关资源
最近更新 更多