Русское сообщество разработки на PHP-фреймворке Laravel.
Ты не вошёл. Вход тут.
Страницы 1
Как очистить память используя Eloquent ORM, мой маленький тест показал что она не очищается. А мне жизненно необходимо выполнить > 100к более сложных итераций, и только из за того что память почему-то не ощищается, переходить со своих 512 мб, на 2гб, платя в несколько раз больше за VPS не хочется.
<?
public function memory()
{
$text = <<<EOT
Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text Text
EOT;
echo $text;
for ($x = 0; $x++ < 10000;) {
Test::create(array('f_1'=>$text));
echo $x."\n";
echo get_file_size(memory_get_usage(true))."\n";
}
}
--
$test = new Test; $test->f_1 = $text; $test->save(); тот же результат;
Использование gc_enable() не помогло.
Изменено la2ha (08.01.2013 06:44:44)
Не в сети
У тебя сложный запрос(ы)? Для критичных мест вроде таких, где сотни/тысячи запросов на один скрипт, я бы использовал сырые запросы через PHPDB::query()
.
Если сырых запросов не хочется, то возможная утечка в том, что Eloquent не вызывает PHPclose_cursor()
после получения всего результата. Исправить это можно в PHPLaravel\Database\Connection::query()
— от PHPexecute()
она получает PHPPDOStatement
, который затем читается в PHPfetch()
, но курсор не закрывается, поэтому запрос и весь его результат остаются висеть в памяти.
Судя по всему исправить это можно только изменением кода ядра напрямую, либо наследованием PHPLaravel\Database\Connection
, перекрытием там нужного метода и затем заменой его в PHPDatabase::$connections
при запуске скрипта, например:
// application/start.php
$connection = Config::get('database.default');
$config = Config::get("database.connections.$connection");
DB::$connections[$connection] = new MyConnection(DB::connect($config), $config);
// алиас в application.config нужно убрать
class DB extends Database {
// изначально функция приватная
static function connect($config) { return parent::connect($config); }
}
// application/libraries/MyConection.php
class MyConnection extends Laravel\Database\Connection {
protected function fetch($statement, $style) {
$result = parent::fetch($statement, $style);
$statement->closeCursor();
return $result;
}
}
Не в сети
// алиас в application.config нужно убрать
Не нашел там алиаса на Laravel\Database\Connection
Куда писать
class DB extends Database {
// изначально функция приватная
static function connect($config) { return parent::connect($config); }
}
???
Не в конфиг же!!
А вообще спасибо большое, а то я уже отчаялся, после того как пол ночи общался в IRC по этому поводу и ничего не помогало.
Уже хотел во всех деструкторах связанных с базой данных написать функции очистки параметров
foreach($this as $item) clear($item) //не так конечно, но суть ясна
А потом подумал что плохо это, в ядро лезть. И очень много классов там учавствует вроде, поэтому подумал уже более мощном VPS по поим подчетам получалось 1 мегабайт за 4 минуты набегает, за сутки следовательно 360 примерно, а скрипт выполняться примерно 3 дня должен. В общем многовато надо ресурсов не на что тратить.
Не в сети
- Не нашел там алиаса на Laravel\Database\Connection
Алиас DB ⇒ Database, а не Connection. Классы можно куда угодно поместить, хоть в application/libraries, хоть в start.php, всё равно они нужны при запуске.
- А вообще спасибо большое, а то я уже отчаялся, после того как пол ночи общался в IRC по этому поводу и ничего не помогало.
Не факт, что это исправит утечку, я сам не пробовал.
- А потом подумал что плохо это, в ядро лезть.
В ядро можно лезть, если ты просто ищешь ошибку. Пока не найдёшь можно править любые файлы руками, а как обнаружишь уже будешь думать о том, как это сделать по-нормальному. Если пытаться всё делать по-нормальному без знания, где точно проблема, это будет очень долго, да и смысл?
Если закрытие курсора не поможет, то используй сырые запросы, с ними точно проблем не будет.
- а скрипт выполняться примерно 3 дня должен.
Мне кажется его проще перезапускать. Разбей план выполнения на маленькие фрагменты — по часу, например, и пусть он прогресс сохраняет в файл и при каждом запуске (по cron’у, например) начинает с прошлого места. Обычно такая схема более гибкая.
Не в сети
Не помогло, написал это напрямую в protected function fetch, точнее не именно это, а так чтоб выполнилось именно это.
Потом выяснил что этот метод вообще не используется.
На счет перезапускать, да, думаю это вариант, правда не самый лучший, т.к. особенность скрипта такая, что ему придятся часа 3 работать просто для того чтоб просто дойти до места на котором остановился - иначе никак, но все же решение.
Но я еще поищу утечку, и если найду - поделюсь.
Не в сети
Не в сети
Сырые запросы приводят к тому же результату почти, на 20% сеньше пямяти съедает.
DB::query('insert into test (f_1) values ("'.$text.'")');
Изменено la2ha (08.01.2013 23:08:59)
Не в сети
Нашел таки, часов 8 на это потратил точно))) Оставлю без комментариев пожалуй.
//application/config/database.php
/*
|--------------------------------------------------------------------------
| Database Query Logging
|--------------------------------------------------------------------------
|
| By default, the SQL, bindings, and execution time are logged in an array
| for you to review. They can be retrieved via the DB::profile() method.
| However, in some situations, you may want to disable logging for
| ultra high-volume database work. You can do so here.
|
*/
'profile' => true,
Не в сети
Не в сети
Оно по умолчанию было включено по мойму.
Не в сети
Написал им предложение отрубить его по умолчанию, и его отрубили, так что следующий релиз уже без этого будет.
Не в сети
- Оно по умолчанию было включено по мойму.
Надо же. Я обычно все настройки пересматриваю сразу как проект начинаю, чтобы особо не зависеть от взглядов разработчиков, которые иногда могут быть неочивидными. У Laravel есть своя специфика — он одновременно подходит для серьёзной разработки, но при этом у него есть какой-то оттенок любительского проекта, проявляющийся в подобных мелочах и способах решения некоторых проблем.
Не в сети
Не в сети
Страницы 1