我有一个 php 脚本作为 ubuntu 上的服务运行,它是一个无限循环,执行外部检查以保存到 mysql 数据库。
它消耗高达1GB内存,使用HTOP命令检查
在 while 的每次迭代中运行 get_memory_usage 命令,我有不同的值,当我不传递 true 参数来获取实际使用情况时,该值保持稳定,但是使用 true 参数,它会随着每次迭代而增长。
Mem: 3.49 mb - 132 mb 02
Mem: 1.01 mb - 132 mb 03
Mem: 4.66 mb - 146 mb 02
Mem: 1.01 mb - 146 mb 03
Mem: 5.01 mb - 148 mb 02
Mem: 1.01 mb - 148 mb 03
Mem: 6.12 mb - 148 mb 02
Mem: 1.01 mb - 148 mb 03
Mem: 6.4 mb - 162 mb 02
Mem: 1.13 mb - 162 mb 03
我已经将执行块分离成while之外的单个函数,并调用了gc_collect_cycles(),但并没有解决问题。
$loop = Array();
gc_enable();
function execute(&$loop, $rep_server){
foreach($rep_server->objetos as $server){
$dates = calcDateGetData("","",0,false,false,2,40);
$loop[$sid]['data_inicial'] = $dates[0];
$params['dataCadastroInicial'] = $loop[$sid]['data_inicial'];
$js_ar = $server->sendRequest(REQUEST::ObterClientesServicos,$params);
if(isset($js_ar["dados"])){
if(count($js_ar["dados"]) > 0){
foreach ($js_ar["dados"] as $key2) {
$cliente = new ClienteServico();
$cliente->uid_ = DB::toUid_($server->id, $key2['id_servico']);
$remoto[] = $cliente;
}
}
$repOs->objetos = $remoto;
$repOs->updateAllChanges($repAll);
}
}
...
...
echo "Mem: ".convertBytes(memory_get_usage())." - ".convertBytes(memory_get_usage(true))." 02 \n";
}
while(true){
echo "Mem: ".convertBytes(memory_get_usage())." - ".convertBytes(memory_get_usage(true))." 01 \n";
execute($loop, $rep_server);
gc_collect_cycles();
DB::getInstancia()->close();
echo "Mem: ".convertBytes(memory_get_usage())." - ".convertBytes(memory_get_usage(true))." 03 \n";
$c = count($opts);
if($c > 1 && $opts[$c-2] == "-d" && is_numeric($opts[$c-1])){
echo PHP_EOL." SLEEP FOR ".$opts[$c-1]."(s)".PHP_EOL;
sleep($opts[$c-1]);
} else
return;
echo "\n";
}
我不认为存在内存泄漏,但是 PHP 释放的内存在 Ubuntu 中没有被释放,有什么想法吗?
您必须使用生成器而不是普通循环。因为生成器不会在循环的每次迭代中创建新对象。他们在每次迭代中重用相同的对象。请参阅:https://www.php.net/manual/en/language.generators.overview.php 然而,这是收集指标的常见任务。此类需求借助很多专门软件(例如:Prometheus、telegraph、zabbix agent等)来解决。