2009-09-11 2 views
10

доктрина, как представляется, принимать свыше 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?

ответ

6

Из того, что я могу видеть, вы код не кажется, неправильно ...


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

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

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 КБ разница - ну, с большими объектами/несколько строк, он все еще может быть хорошей идеей, ...


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


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

+0

Это меня беспокоит, поскольку я интегрирую Доктрину в свои рамки. –

+0

Прежде чем беспокоиться об этом, вы можете захотеть сделать еще несколько тестов, с большими таблицами, большим количеством данных и всем этим - чтобы увидеть, является ли увеличение памяти линейным или нет. ;; Кстати: я видел, как использование Doctrine в проектах основано как на Zend Framework, так и на Symfony, и это никогда не было проблемой ... –

+0

Pascal MARTIN: Возможно, эти сайты, о которых вы знаете, не имеют больших нагрузок? Я хотел бы знать, используют ли какие-либо основные сайты Doctrine. – Fragsworth

4

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

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

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

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

5

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

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

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

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

Result без APC:

10.25 megabytes 
RV David 
16.5 megabytes 

Result с APC:

3 megabytes 
RV David 
4.25 megabytes 

кэширование Опкод делает очень существенную разницу.

2

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

Для того, чтобы использование памяти немного меньше Вы можете попробовать использовать ниже код:

  • $ Запись-> бесплатно (правда) - будет делать глубокие бесплатные вверх, созывает бесплатно() на всех отношения тоже
  • $ галерею-> бесплатно() - это освободит все коллекции ссылка
  • Doctrine_Manager :: соединения() -> чистых()/Clear() - соединение очистки (и удаление записей тождественных)
  • $ query-> free()
1

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

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

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

0

Я просто "daemonized" сценарий с Symfony 1.4 и установив следующие остановил память коробления:

sfConfig::set('sf_debug', false); 
+0

Это полезно делать, если вы используете доктрину + symfony, но не поможет, если вы просто используете Doctrine. –

+0

Соглашаясь с Ikon, В symfony профайлер-гобыл. поэтому: 'sfConfig :: set ('sf_debug', false); ** ПЕРЕД ** соединение с базой данных будет значительно упрощено, если, как и я, вы выгружаете большие таблицы в csv. вы можете сделать это в * frontend_dev.php * или аналогичном (3-й параметр). – 2011-06-01 23:14:23

4

Осторожно с fetchOne() на Doctrine Query.Вызов этой функции не будет добавлять «Limit 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; 
} 
Смежные вопросы