PHP的垃圾收集器不起作用?

时间:2018-08-04 11:38:15

标签: php laravel php-7

我有基于Laravel的应用程序,可在php 7.0上运行

从某种意义上说,队列工作器php artisan queue:work --daemon会占用大量内存,因此存在问题。

开始处理的基本代码如下(仅显示重要部分)

<?php

namespace App\Jobs;

class TaskCronJoib extends Job implements ShouldQueue
{
   use InteractsWithQueue, SerializesModels;

   private $type;

   public function __construct(string $type)
   {
      $this->type = $type;
   }

    public function handle()
    {
        $handler = app()->make(HandlerFactory::class)->get($this->type);
        $handler->process();
    }
}

我已经测试(并且可以正常工作),当我在handle()的末尾添加gc_collect_cycles()时,随着时间的推移它消耗的内存将大大减少。

我已经测试(并且可以正常工作),当我在handle()的末尾添加gc_collect_cycles()时,随着时间的推移它消耗的内存将大大减少。

    public function handle()
    {
        $handler = app()->make(HandlerFactory::class)->get($this->type);
        $handler->process();
        gc_collect_cycles();
    }

Laravel的工作人员会无限期地工作,因此通常每个PHP进程都工作6个小时或事件12个小时。我在crontab和超级用户中使用php artisan queue:restart来定期重新启动进程,以免仍然消耗内存。

TLDR:为什么添加gc_collect_cycles()会导致PHP消耗更少的内存?

默认情况下启用垃圾收集器

php -i | grep enable_gc                                                
zend.enable_gc => On => On

没有类似的电话     gc_disable();     ini_set('zend.enable_gc',false);

2 个答案:

答案 0 :(得分:0)

据我所知,--daemon实际上是一个持久性请求,因此默认情况下不会清除内存。如果handle()是短暂的,我会考虑使用queue:listen,因为这将在任务完成后结束请求,这将自动释放内存。如果这些任务中的两个可能同时发生(又是很长的任务,需要很长时间才能完成),则gc_collect_cycles()和--daemon标志可能就足够了。

但是,与手动转储gc周期相关的性能开销。因此,经常执行此操作会降低性能-如果handle()是一个短暂的过程,可能不值得引入gc_collect_cycles()。取决于体系结构以及背景情况。如果这是一个短暂且持续不断的进程,则可能是保持持久守护程序并手动转储gc而不是上下启动Laravel的情况。真的只是取决于。

gc_collect_cycles()只会以更高的频率转储周期,而不是自动转储。通常,对于单个请求,它会一直等待到任意数量的zval,即10,000,然后自动检查可以从根缓冲区中转储的内容。或者它在请求结束时自动处理它。可以通过PHP配置和重新编译更改该数字。

PHP 7.3还将对垃圾回收进行一些改进(对于某些情况,不是一般情况),因此请确保在可能的情况下更新PHP。

来源:

Laravel Daemon Queue Memory Leak

http://php.net/manual/en/features.gc.collecting-cycles.php

答案 1 :(得分:0)

我正在使用以下代码删除来宾会话文件,这可能会有所帮助:

    $c = 0;
    $files = File::files(storage_path().'/framework/sessions');

    foreach ($files as $f) {
        $file_content = file_get_contents($f);

        $arrFileData = unserialize($file_content);
        $dtCreated = Carbon::createFromTimestamp($arrFileData['_sf2_meta']['u']);
        $dtNow = Carbon::now();
        $diffInHours = $dtNow->diffInHours($dtCreated);
        //if file is older than 2h & not found 'login_web_' then remove file
        if ($diffInHours > 2 && strpos($file_content, 'login_web_') === false) {
            $c++;
            @unlink($f);
        }
    }
    echo "Clear unnecessary sessions: ".$c;