Использование памяти для запросов Doctrine - PullRequest
10 голосов
/ 11 сентября 2009

Doctrine, похоже, требует более 4 МБ ОЗУ для выполнения одного простого запроса:

print memory_get_peak_usage()." <br>\n";
$q = Doctrine_Query::create()
    ->from('Directories d')
    ->where('d.DIRECTORY_ID = ?', 5);

$dir = $q->fetchOne();
print $dir['name']." ".$dir['description']."<br>\n";

print memory_get_peak_usage()." <br>\n";

/***************  OUTPUT:  **************************

6393616
testname testdescription
10999648

/***************************************************/

Это тестовая база данных с очень небольшим количеством данных - элемент, который я запрашиваю, не содержит никаких данных, кроме отображаемых здесь.

Возможно, что-то не так с тем, как я настроил систему, или это стандартное использование памяти для Doctrine?

Ответы [ 7 ]

6 голосов
/ 11 сентября 2009

Из того, что я вижу, ваш код, кажется, не ошибается ...


В качестве теста я создал быстрый пример с очень простой таблицей (только четыре поля) .

Вот соответствующий код:

var_dump(number_format(memory_get_peak_usage()));

$test = Doctrine::getTable('Test')->find(1);

var_dump(number_format(memory_get_peak_usage()));

При этом у меня есть такой вывод:

string '1,316,088' (length=9)
string '2,148,760' (length=9)

Учитывая, что таблица действительно проста, и что я выбираю только одну строку, мне это тоже кажется "много" - но это вполне соответствует тому, что вы получаете, и тому, что я видел в других проектах: - (


Если вам нужно только отображать ваши данные, а не работать с ними (т.е. обновлять / удалять / ...), решение может состоять в том, чтобы не извлекать сложные объекты, а только простой массив:

$test = Doctrine::getTable('Test')->find(1, Doctrine::HYDRATE_ARRAY);

Но, в данном случае, это не имеет большого значения, на самом деле :-(:

string '1,316,424' (length=9)
string '2,107,128' (length=9)

Только 40 КБ разницы - ну, с большими объектами / большим количеством линий, это может быть хорошей идеей ...


В руководстве по доктрине есть страница под названием Улучшение производительности ; Может быть, это может помочь вам, особенно для этих разделов:


О, кстати: я сделал этот тест на PHP 5.3.0; может быть, это может повлиять на количество используемой памяти ...

5 голосов
/ 10 октября 2009

Я согласен с ответом Романа - использование кеша OpCode является обязательным условием при использовании больших библиотек / библиотек.

Пример, связанный с кэшированием OpCode

Я недавно принял использование Doctrine с Zend Framework и мне было любопытно использовать память - поэтому, как и OP, я создал метод, использующий критерии, аналогичные тесту OP, и провел его как общий тест, чтобы увидеть, какой пик ZF + Doctrine использование памяти будет.

Я получил следующие результаты:

Результат без APC:

10.25 megabytes
RV David
16.5 megabytes

Результат с APC:

3 megabytes
RV David
4.25 megabytes

Кэширование кода операции имеет очень важное значение.

4 голосов
/ 16 мая 2012

Осторожно с fetchOne () при запросе доктрины. Этот вызов функции не добавит «Предел 1» в SQL

Если вам просто нужно получить одну запись из БД, убедитесь:

$q->limit(1)->fetchOne() 

Использование большого количества памяти на большом столе значительно снижено.

Вы могли видеть, что fetchOne () будет сначала извлекать данные из БД в виде коллекции, а затем возвращать первый элемент.

public function fetchOne($params = array(), $hydrationMode = null)
{
    $collection = $this->execute($params, $hydrationMode);

    if (is_scalar($collection)) {
        return $collection;
    }

    if (count($collection) === 0) {
        return false;
    }

    if ($collection instanceof Doctrine_Collection) {
        return $collection->getFirst();
    } else if (is_array($collection)) {
        return array_shift($collection);
    }

    return false;
}
4 голосов
/ 28 сентября 2009

Ну, откуда это использование памяти? Как отметил Паскаль МАРТИН, гидратация массива не имеет большого значения, что логично, поскольку речь идет только о нескольких записях.

Потребление памяти происходит от всех классов, которые загружаются по запросу через автозагрузку.

Если у вас не настроен APC, тогда да, что-то не так с настройкой вашей системы. Даже не начинайте измерять производительность и ожидать хороших результатов с любой большой библиотекой php без кеша кода операции, такого как APC. Это не только ускорит выполнение, но и сократит использование памяти как минимум на 50% для всех загрузок страницы, кроме самой первой (где APC сначала необходимо кэшировать байт-коды).

И 4MB в вашем простом примере действительно пахнет как no-APC, в противном случае он был бы немного выше.

2 голосов
/ 21 февраля 2010

Doctrine предоставляет функцию free () для Doctrine_Record, Doctrine_Collection и Doctrine_Query, которая устраняет циклические ссылки на эти объекты, освобождая их для сбора мусора. Подробнее ..

Чтобы использовать память немного меньше Вы можете попробовать использовать следующий код:

  • $ record-> free (true) - выполнит глубокую блокировку, вызовы free () также для всех отношений
  • $ collection-> free () - это освободит все ссылки на коллекции
  • Doctrine_Manager :: connection () -> clean () / clear () - очистить соединение (и удалить записи карты идентификации)
  • $ query-> свободный ()
1 голос
/ 07 марта 2010

Я бы предположил, что большая часть этой памяти используется для загрузки классов Doctrine, а не для объектов, связанных с самим запросом.

  • Какую версию Doctrine вы используете?
  • Вы используете автозагрузчик?

В Doctrine 1.1 поведение автозагрузки по умолчанию называется «агрессивным», что означает, что оно загружает все ваши классы моделей, даже если вы используете только один или два для какого-либо конкретного запроса. Установка этого поведения на «консервативный» уменьшит использование памяти.

0 голосов
/ 20 апреля 2010

Я только что сделал «демонизированный» скрипт с symfony 1.4, и установка следующего остановила захват памяти:

sfConfig::set('sf_debug', false);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...