2009-09-11 19 views
10

Doktryna wydaje się być przy ponad 4 MB pamięci RAM, aby wykonać pojedyncze, proste zapytanie:Doktryna wykorzystanie pamięci zapytanie

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 

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

To na bazie testowej z bardzo niewiele danych w nim - pozycja, że ​​jestem kwerenda nie zawiera żadnych danych poza tym, co jest tutaj wyświetlane.

Czy jest jakiś problem ze sposobem, w jaki mam skonfigurowany system, czy też jest to standardowe użycie pamięci dla Doctrine?

Odpowiedz

6

Z tego co widzę, ty kod nie wydają się być źle ...


Jako test, mam skonfigurować szybkie przykład, z bardzo prostej tabeli (tylko cztery pola).

Oto odpowiedni kod:

var_dump(number_format(memory_get_peak_usage())); 

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

var_dump(number_format(memory_get_peak_usage())); 

Kiedy robi, że mam tego rodzaju wyjścia:

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

Zważywszy tabeli jest bardzo prosta, a ja tylko ściągam jedną linię, Wydaje mi się, że jest to "wiele" - ale jest to całkiem zgodne z tym, co dostrzegasz, i z tym, co zobaczyłem w innych projektach :-(


Jeśli tylko trzeba wyświetlić swoje dane, a nie z nim pracować (czyli zmiana/kasowanie/...), rozwiązaniem może być nie do pobierania skomplikowanych obiektów, ale tylko prosta tablica:

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

Ale w tym przypadku, to nie robi wielkiej różnicy, rzeczywiście :-(:

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

Tylko 40 KB różnicy - dobrze, z większych obiektów/więcej linii, to nadal może być dobrym pomysłem ...


W podręczniku doktryny znajduje się strona o nazwie Improving Performance; Może to może pomóc, zwłaszcza dla tych sekcjach:


Oh, btw: Zrobiłem test na PHP 5.3.0; może to może mieć wpływ na ilość wykorzystanej pamięci ...

+0

To mnie martwi, ponieważ włączam Doctrine do mojej struktury. –

+0

Przed martwiąc się zbytnio, możesz chcieć zrobić więcej testów, z większymi tabelami, więcej danych i wszystko to - aby sprawdzić, czy wzrost pamięci jest liniowy czy nie. ;; btw: Widziałem, jak Doctrine używa w projektach opartych zarówno na Zend Framework, jak i Symfony, i to nigdy nie było problemem ... –

+0

Pascal MARTIN: Być może te strony, o których wiesz, nie mają dużych obciążeń? Chciałbym wiedzieć, czy jakiekolwiek główne strony używają Doctrine. – Fragsworth

4

No cóż, skąd bierze się to użycie pamięci? Jak zauważył Pascal MARTIN, uwadnianie macierzy nie robi wielkiej różnicy, co jest logiczne, ponieważ mówimy tu tylko o kilku rekordach.

Zużycie pamięci pochodzi ze wszystkich klas, które są ładowane na żądanie przez automatyczne ładowanie.

Jeśli nie masz skonfigurowanego APC, to tak, jest coś nie tak z ustawieniem systemu. Nie zaczynaj nawet mierzyć wydajności i oczekiwać dobrych wyników z dowolną dużą biblioteką php bez pamięci podręcznej kodu, takiej jak APC.Przyspieszy to nie tylko wykonanie, ale także ograniczy zużycie pamięci o co najmniej 50% na wszystkich ładowaniach stron, z wyjątkiem pierwszego (gdzie APC musi najpierw buforować bajtki).

I 4MB z twoim prostym przykładem naprawdę pachnie jak nie-APC, w przeciwnym razie byłby naprawdę wysoki.

5

Zgadzam się z odpowiedzią romanb - używanie pamięci podręcznej OpCode jest koniecznością podczas używania dużych bibliotek/frameworków.

Przykład związany buforowania OPCODE

I niedawno przyjęty zwyczaj Doktryna z Zend Framework i był ciekaw zużycie pamięci - tak jak PO, stworzyłem metodę stosując podobne kryteria testu i OPS uruchomił go jako ogólny test, aby zobaczyć, jakie będzie wykorzystanie pamięci szczytowej ZF + Doctrine.

Mam następujące wyniki:

Rezultatów bez APC:

10.25 megabytes 
RV David 
16.5 megabytes 

wynik z APC:

3 megabytes 
RV David 
4.25 megabytes 

Opcode buforowanie sprawia, że ​​bardzo istotną różnicę.

2

Doctrine udostępnia funkcję free() w Doctrine_Record, Doctrine_Collection i Doctrine_Query, która eliminuje odwołania kołowe do tych obiektów, uwalniając je do zbierania śmieci. More info..

Aby zużycie pamięci trochę mniej Można spróbować użyć kodu folowing:

  • $ Nagrywania> free (true) - zrobi głębokie bezpłatne-up'S, wywołuje free() na wszystkich Stosunki zbyt
  • $ Collection-> free() - to uwolni cały zbiór odwołuje
  • Doctrine_Manager :: połączenia() -> clean()/clear() - połączenia oczyszczania (i usunąć wpisy tożsamość mapie)
  • $ query-> free()
1

Przypuszczam, że większość tej pamięci jest używana do ładowania klas Doctrine, a nie do obiektów powiązanych z samym zapytaniem.

  • Którą wersję Doctrine używasz?
  • Czy używasz autoloadera?

W Doctrine 1.1 domyślne zachowanie automatyczne jest nazywane "agresywnym", co oznacza, że ​​ładuje wszystkie klasy modeli, nawet jeśli używasz tylko jednego lub dwóch na konkretne żądanie. Ustawienie tego zachowania na "konserwatywne" zmniejszyłoby zużycie pamięci.

0

Właśnie nie "daemonized" skrypt z symfony 1.4 i ustawiając następujące zatrzymał pamięć wyginanie:

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

To jest dobre rozwiązanie, jeśli używasz doktryny + symfony, ale nie pomoże, jeśli używasz Doctrine. –

+0

Zgadzam się z Ikoną, W symfony profiler gobals ram. więc: 'sfConfig :: set ('sf_debug', false);' ** PRZED ** połączenie z bazą danych zostanie znacznie ułatwione, jeśli, tak jak ja, zrzucasz duże tabele do pliku CSV. możesz to zrobić w * frontend_dev.php * lub podobnym (3rd param). –

4

ostrożność fetchOne() na Doctrine Query.To wywołanie funkcji nie doda „Granica 1” na SQL

Jeśli wystarczy, aby jeden rekordy od DB, upewnij się, że:

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

Pamięć użycie jest ogromny spadł na dużym stole.

Możesz zobaczyć, że fetchOne() pobierze z DB jako kolekcję, a następnie zwróci pierwszy element.

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; 
} 
Powiązane problemy