Script/Queue 保持 运行 内存不足
Script/Queue keeps running out of memory
我的应用程序有大量数据需要在用户请求时处理。该脚本最初是在 foreach 循环中组织的,但这导致 PHP 每次都超时。我转而使用 Redis 队列,但后来我遇到了内存问题。
mmap() failed: [12] Cannot allocate memory
和
PHP Fatal error: Out of memory (allocated 79691776) (tried to allocate 134217728 bytes)
现在我已经将队列设置为只有一个进程。它工作得更好,但过了一会儿我又开始出现内存错误。这只是我在测试它。一旦用户开始使用它,它就会倒下。
我为脚本分配了 1024MB,因为如果我不一次性使用它,它 运行 就会内存不足。我想知道每次脚本 运行 释放内存后我是否可以做些什么。喜欢取消设置变量?我看不出这有什么帮助,因为脚本结束并且队列工作人员从头开始 运行。
我正在使用具有 2GB RAM 的流浪机器 (Homestead)
更新:
当我们执行调度程序时,回测开始 运行s 通过 10 个联盟和 10 年。
调度员class:
class Dispatcher
{
use Attributes;
use DataRetriever;
public function runBacktest($token)
{
$authUserId = Auth::user()->id;
$system = System::where('token', $token)->first();
$this->getSystem( $authUserId, $system->id);
foreach ($this->leagues as $league) {
foreach ($this->years as $year) {
BacktestJob::dispatch($authUserId, $system->id, $token, $league, $year);
}
}
}
}
调度员执行作业:
class BacktestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $token;
private $league;
private $year;
private $authUserId;
private $systemId;
public $timeout = 10000;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($authUserId, $systemId, $token, $league, $year)
{
$this->token = $token;
$this->league = $league;
$this->year = $year;
$this->authUserId = $authUserId;
$this->systemId = $systemId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$backtest = new Backtest;
$backtest->init($this->authUserId, $this->systemId, $this->token, $this->league, $this->year);
}
}
下面是主脚本的精简版,因为它做了很多事情:
public function init($authUserId, $systemId, $token, $league, $year)
{
// ini_set('memory_limit', -1);
ini_set('max_execution_time', 300); //300 seconds = 5 minutes
ini_set('memory_limit', '1024M'); // or you could use 1G
$this->authUserId = $authUserId;
$this->systemId = $systemId;
$this->token = $token;
include(storage_path("app/matches/{$league->key}/{$year}.php"));
$this->leagueResults[$league->key][$year] = collect($this->leagueResults[$league->key][$year]);
//Loops through the data - saves to new array
fwrite($file, serialize($backtest));
最初数据是从一个 50MB json 文件中提取的。我用硬编码的 PHP 数组(文件大小 100MB)替换了 json 文件。我知道较新的文件更大,但我假设不去 json_decode 会加快速度。
我还删除了脚本末尾的数据库插入,但我更希望它保留,因为它会让我的生活更轻松。
好的,我通过分解数据文件解决了这个问题。因为我可以完全访问原始数据文件,而且我不需要每个请求都包含其中的所有数据,所以我将其分成大约 50 个较小的文件。
我对提高的性能感到惊讶。从 30 多秒加上超时,它下降到不到 2 秒。大多数请求在不到一秒内完成。
我的应用程序有大量数据需要在用户请求时处理。该脚本最初是在 foreach 循环中组织的,但这导致 PHP 每次都超时。我转而使用 Redis 队列,但后来我遇到了内存问题。
mmap() failed: [12] Cannot allocate memory
和
PHP Fatal error: Out of memory (allocated 79691776) (tried to allocate 134217728 bytes)
现在我已经将队列设置为只有一个进程。它工作得更好,但过了一会儿我又开始出现内存错误。这只是我在测试它。一旦用户开始使用它,它就会倒下。
我为脚本分配了 1024MB,因为如果我不一次性使用它,它 运行 就会内存不足。我想知道每次脚本 运行 释放内存后我是否可以做些什么。喜欢取消设置变量?我看不出这有什么帮助,因为脚本结束并且队列工作人员从头开始 运行。
我正在使用具有 2GB RAM 的流浪机器 (Homestead)
更新:
当我们执行调度程序时,回测开始 运行s 通过 10 个联盟和 10 年。
调度员class:
class Dispatcher
{
use Attributes;
use DataRetriever;
public function runBacktest($token)
{
$authUserId = Auth::user()->id;
$system = System::where('token', $token)->first();
$this->getSystem( $authUserId, $system->id);
foreach ($this->leagues as $league) {
foreach ($this->years as $year) {
BacktestJob::dispatch($authUserId, $system->id, $token, $league, $year);
}
}
}
}
调度员执行作业:
class BacktestJob implements ShouldQueue
{
use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;
private $token;
private $league;
private $year;
private $authUserId;
private $systemId;
public $timeout = 10000;
/**
* Create a new job instance.
*
* @return void
*/
public function __construct($authUserId, $systemId, $token, $league, $year)
{
$this->token = $token;
$this->league = $league;
$this->year = $year;
$this->authUserId = $authUserId;
$this->systemId = $systemId;
}
/**
* Execute the job.
*
* @return void
*/
public function handle()
{
$backtest = new Backtest;
$backtest->init($this->authUserId, $this->systemId, $this->token, $this->league, $this->year);
}
}
下面是主脚本的精简版,因为它做了很多事情:
public function init($authUserId, $systemId, $token, $league, $year)
{
// ini_set('memory_limit', -1);
ini_set('max_execution_time', 300); //300 seconds = 5 minutes
ini_set('memory_limit', '1024M'); // or you could use 1G
$this->authUserId = $authUserId;
$this->systemId = $systemId;
$this->token = $token;
include(storage_path("app/matches/{$league->key}/{$year}.php"));
$this->leagueResults[$league->key][$year] = collect($this->leagueResults[$league->key][$year]);
//Loops through the data - saves to new array
fwrite($file, serialize($backtest));
最初数据是从一个 50MB json 文件中提取的。我用硬编码的 PHP 数组(文件大小 100MB)替换了 json 文件。我知道较新的文件更大,但我假设不去 json_decode 会加快速度。
我还删除了脚本末尾的数据库插入,但我更希望它保留,因为它会让我的生活更轻松。
好的,我通过分解数据文件解决了这个问题。因为我可以完全访问原始数据文件,而且我不需要每个请求都包含其中的所有数据,所以我将其分成大约 50 个较小的文件。
我对提高的性能感到惊讶。从 30 多秒加上超时,它下降到不到 2 秒。大多数请求在不到一秒内完成。