2016-08-31 16 views
3

laravel 5.1을 사용하고 수퍼바이저를 사용하여 대기열 작업을 모니터링하고 있습니다. 큐 드라이버는 데이터베이스입니다.Laravel Daemon Queue Memory Leak

[program:queue] 
process_name=%(program_name)s_%(process_num)02d 
command=php /var/www/html/artisan queue:work database --sleep=3 --tries=1 --daemon 
autostart=true 
autorestart=true 
user=root 
numprocs=1 
redirect_stderr=true 
stdout_logfile=/var/www/html/storage/logs/supervisord.log 

대기열 수신기에서 사용하는 RAM은 각 작업을 처리 한 후에 증가하며 최대 150-200MB까지 올라갑니다. 모든 전역 변수에는 null이 할당됩니다.

namespace App\Jobs; 
use App\Jobs\Job; 
use App\Compatibility; 
use App\Like; 
use App\Message; 
use Illuminate\Queue\SerializesModels; 
use Illuminate\Queue\InteractsWithQueue; 
use Illuminate\Contracts\Bus\SelfHandling; 
use Illuminate\Contracts\Queue\ShouldQueue; 

class CalculateInteractionLike extends Job implements SelfHandling, ShouldQueue 
{ 
    use InteractsWithQueue, SerializesModels; 
    protected $userAId; 
    protected $userBId; 
    protected $gender; 

    /** 
    * Create a new job instance. 
    * 
    * @return void 
    */ 
    public function __construct($userAId, $userBId, $gender) 
    { 
     $this->userAId = $userAId; 
     $this->userBId = $userBId; 
     $this->gender = $gender; 
    } 

    /** 
    * Execute the job. 
    * 
    * @return void 
    */ 
    public function handle() 
    { 
     echo 'start CalculateInteractionLike '. memory_get_usage() . "\n"; 
     $userArray = array(); 
     Compatibility::where('userAId', $this->userBId)->where('userBId', $this->userAId)->update(['interactionAB'=>0.0001]); 
     $profiles = Compatibility::where('userAId', $this->userBId)->where('interactionAB', '>',0)->orderBy('compatibilityAB', 'desc')->take(4)->get(['compatibilityAB']); 
     $compatible = array(); 
     for($i=0; $i<sizeof($profiles);$i++){ 
      $compatible[] = $profiles[$i]->compatibilityAB; 
     } 
     $std = sizeof($compatible)>1 ? $this->_calculateStd($compatible) : 0; 
     $messagedProfile = Message::where('userBId', $this->userBId)->where('type', '1')->get(['userAId']); 
     for($i=0;$i<sizeof($messagedProfile);$i++){ 
      Compatibility::where('userAId',$this->userBId)->where('userBId', $messagedProfile[$i]->userAId)->update(array('interactionAB' => $std)); 
     } 
     $this->userAId = null; 
     $this->userBId = null; 
     $this->gender = null; 
     $userArray = null; 
     $profiles = null; 
     $compatible = null; 
     $std = null; 
     $messagedProfile = null; 

    } 

    private function _calculateStd($compatible){ 
     return sqrt(array_sum(array_map([$this,"_stdSquare"], $compatible, array_fill(0,count($compatible), (array_sum($compatible)/count($compatible)))))/(count($compatible)-1)); 
    } 

    private static function _stdSquare($x, $mean){ 
     return pow($x - $mean, 2); 
    } 

    public function __destruct(){ 
     $this->cleanup(); 
     echo 'end CalculateInteractionLike '. memory_get_usage() . "\n"; 
    } 

    public function cleanup() { 
     //cleanup everything from attributes 
     foreach (get_class_vars(__CLASS__) as $clsVar => $_) { 
      unset($this->$clsVar); 
     } 
    } 
} 

위의 작업이 처리 될 때마다 RAM이 약간 증가합니다. 어떤 아이디어? > 함수를 호출하기 -

+0

프로세스가 시작될 때 메모리를 얼마나 소비합니까? –

+0

계속 증가하여 190-200MB가됩니다. 그 후 다시 시작했습니다. –

+0

memory = 128은 적어도 하나의 작업이 처리되지만 이전에는 자동으로 재시작되지 않음을 의미합니다. –

답변

0

당신이 메모리를 청소하지 않는 유일한 장소가 내부에은()

 for($i=0;$i<sizeof($messagedProfile);$i++){ 
      Compatibility::where('userAId',$this->userBId)->where('userBId', $messagedProfile[$i]->userAId)->update(array('interactionAB' => $std)); 
     } 

정적 (:: 사용)하지만 내부적으로 생성 객체입니다 처음에는 사용하기 시작 . Desctuctors가 있는지 확인하고 가비지 컬렉터를 수동으로 호출하려고 했습니까?

  for($i=0;$i<sizeof($messagedProfile);$i++){ 
       $tmp = Compatibility::where('userAId',$this->userBId)->where('userBId', $messagedProfile[$i]->userAId)->update(array('interactionAB' => $std)); 
$tmp = null; 
      } 

유의하시기 바랍니다 PHP < 7.0을 자동으로 소멸되지 않은 : 당신이 시도하고 싶은 네, 그래서 만약

for($i=0;$i<sizeof($messagedProfile);$i++){ 
      Compatibility::where('userAId',$this->userBId)->where('userBId', $messagedProfile[$i]->userAId)->update(array('interactionAB' => $std)); 
      gc_collect_cycles(); 
     } 

두 번째 것를 Where(), 갱신() 등 객체에 대한 참조를 반환 할 수 있습니다 상위 클래스 내부에서 작성된 클래스의 오브젝트 확인이 : 주위의 작품으로 https://codereview.stackexchange.com/questions/57847/case-of-the-hidden-memory-leak

0

- 당신은 메모리 누수의 원인을 찾을 수없는 경우 - 당신은 그냥 데몬 플래그없이 queue:listen로 전환 할 수 있습니다.

이렇게하면 각 작업 후에 프레임 워크가 "재부팅"되어 PHP에 의해 모든 메모리가 해제됩니다.

이것은 감독자와 호환되며 queue:listen이 항상 다시 시작되도록합니다.