babahalki
Постоялец
- Регистрация
- 6 Май 2016
- Сообщения
- 247
- Реакции
- 107
- Автор темы
- #1
Всем привет.
Столкнулся с нехваткой 512мб для выполнения скрипта. Расстановка get_memory_usage() показала, что памяти хватает на выполнение главного цикла, но на втором цикле память не освобождалась, в результате fatal error.
Сломал себе всю голову. Сначала делал обнуление всех переменных после их использования. через $var = ''; $var = null;
Потом делал unset($var);
Потом сразу и то и другое. Ничего не помогало.
Дальше сделал следующее, поделил весь скрипт на 3 функции. Насколько я правильно понял, после выполнения функции все ее локальные переменные и их данные выгружаются из памяти.
Получилось вот такие 3 функции.
Первая функция делает многомерный массив с набором параметров id, name, value. Она выполняется дважды с разными параметрами, чтобы получить 2 массива.
Вторая функция перемножает 2 массива между собой и выдает массив. id, id2, name, name2, но так чтобы если есть пара id=>1 id2=>2, пара id=>2 id2=>1 не создавалась.
3 функция пишет массив в xml файл.
в самой программе следующее.
Потребление памяти не изменилось, до функции 80мб, после функции 170мб, дальше fatal error.
Стоило мне поменять цикл с foreach на while, и все заработало, поменял только в третьей функции, которая писала большой массив в файл.
Вопрос заключается в следующем. Чем отличаются циклы foreach и while с точки зрения потребления памяти?
Почему локальные переменные и их данные после выполнения функции не освобождали память?
Столкнулся с нехваткой 512мб для выполнения скрипта. Расстановка get_memory_usage() показала, что памяти хватает на выполнение главного цикла, но на втором цикле память не освобождалась, в результате fatal error.
Сломал себе всю голову. Сначала делал обнуление всех переменных после их использования. через $var = ''; $var = null;
Потом делал unset($var);
Потом сразу и то и другое. Ничего не помогало.
Дальше сделал следующее, поделил весь скрипт на 3 функции. Насколько я правильно понял, после выполнения функции все ее локальные переменные и их данные выгружаются из памяти.
Получилось вот такие 3 функции.
Первая функция делает многомерный массив с набором параметров id, name, value. Она выполняется дважды с разными параметрами, чтобы получить 2 массива.
Код:
function feat_opt ($f0_ids, $f0_object, $c) {
$okay = new Okay();
$o0_object = $okay->features->get_categories_options(array('category_id'=>$c->children, 'feature_id'=>$f0_ids));
dtimer::reset();
foreach($o0_object as $o0) {
foreach($f0_object as $f0) {
if ($f0->id == $o0->feature_id) {
//$features_array[] = array($f0->id=>array($o0->translit));
$feat_opt[] = array('name'=>$f0->name, 'url'=>$f0->url, 'id'=>$f0->id, 'value'=>$o0->value, 'translit'=>$o0->translit);
}
}
}
return $feat_opt;
}
Вторая функция перемножает 2 массива между собой и выдает массив. id, id2, name, name2, но так чтобы если есть пара id=>1 id2=>2, пара id=>2 id2=>1 не создавалась.
Код:
function feat_mix ($feat0, $feat1) {
$okay = new Okay();
$keys = array();
$k1 = 0;
foreach($feat0 as $opt0) {
$k1++;
$k2 = 0;
foreach($feat1 as $opt1) {
$k2++;
if ($opt0['id'] != $opt1['id']) {
$key = $k1 * $k2 + $k1 + $k2;
if (!array_key_exists($key,$keys)) {
$keys[$key] = 1;
$feat_opt_mix[] = array(
'key' => $key,
'name'=>$opt0['name'],
'url'=>$opt0['url'],
'id'=>$opt0['id'],
'value'=>$opt0['value'],
'translit'=>$opt0['translit'],
'name2'=>$opt1['name'],
'url2'=>$opt1['url'],
'id2'=>$opt1['id'],
'value2'=>$opt1['value'],
'translit2'=>$opt1['translit']
);
}
}
}
}
return $feat_opt_mix;
}
3 функция пишет массив в xml файл.
Код:
function write_file ($feat_mix) {
foreach($feat_mix as $opt) {
$f0_name = $opt['name'];
$f0_url = $opt['url'];
$o0_value = $opt['value'];
$o0_translit = $opt['translit'];
$f1_name = $opt['name2'];
$f1_url = $opt['url2'];
$o1_value = $opt['value2'];
$o1_translit = $opt['translit2'];
$url = '/catalog/'.esc($c->url).'/'.esc($f0_url).'-'.esc($o0_translit).'/'.esc($f1_url).'-'.esc($o1_translit);
$last_modify = $c->last_modify;
$last_modify = substr($last_modify, 0, 10);
file_put_contents("temp.xml", "<url>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "<loc>$url</loc>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "<lastmod>$last_modify</lastmod>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "</url>"."\n", FILE_APPEND);
}
return null;
}
в самой программе следующее.
Код:
print "before write_file memory usage: ".memory_get_usage(true)." bytes\r\n";
write_file(feat_mix(feat_opt($f0_ids, $f0_object, $c), feat_opt($f1_ids, $f1_object, $c)));
}
print "after write_file memory usage: ".memory_get_usage(true)." bytes\r\n";
Потребление памяти не изменилось, до функции 80мб, после функции 170мб, дальше fatal error.
Стоило мне поменять цикл с foreach на while, и все заработало, поменял только в третьей функции, которая писала большой массив в файл.
Код:
function write_file ($feat_mix) {
while(count($feat_mix) > $i) {
$f0_name = $feat_mix[$i]['name'];
$f0_url = $feat_mix[$i]['url'];
$o0_value = $feat_mix[$i]['value'];
$o0_translit = $feat_mix[$i]['translit'];
$f1_name = $feat_mix[$i]['name2'];
$f1_url = $feat_mix[$i]['url2'];
$o1_value = $feat_mix[$i]['value2'];
$o1_translit = $feat_mix[$i]['translit2'];
$url = '/catalog/'.esc($c->url).'/'.esc($f0_url).'-'.esc($o0_translit).'/'.esc($f1_url).'-'.esc($o1_translit);
$last_modify = $c->last_modify;
$last_modify = substr($last_modify, 0, 10);
file_put_contents("temp.xml", "<url>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "<loc>$url</loc>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "<lastmod>$last_modify</lastmod>"."\n", FILE_APPEND);
file_put_contents("temp.xml", "</url>"."\n", FILE_APPEND);
$i++;
}
return null;
}
Вопрос заключается в следующем. Чем отличаются циклы foreach и while с точки зрения потребления памяти?
Почему локальные переменные и их данные после выполнения функции не освобождали память?