Wpis z mikrobloga

#programowanie #php #dev

No dobra, dzisiaj muszę pobrać ze dane ze strony. Uzywam #symfony2 i #goutte
Mam już wszystko gotowe, skrypt działa i w ogóle. Problem jest taki że strona ma ogromną ilość podstron.
Np

Lista elementów:
|- Lista obiektów:
|- spis
|- spis
|- spis
|- Lista obiektów:
|- spis
|- spis
|- spis
|- Lista obiektów:
|- spis
|- spis
|- spis

więc wychodzi tego naprawdę dużo. Problem mam taki że na początku skrypt w miarę fajnie leci, i ETA wychodzi około 2h. Ale po 20 minuach wzrazta już do 3h a po kolejnych do 7 i tak dalej..

Zrobiłem taki myk:

$em = $this->getContainer()->get('doctrine')->getEntityManager();
$em->getConnection()->getConfiguration()->setSQLLogger(null);

Ale niewiele to dało... Przez przeglądarkę strona mi się odpala od strzału, nie ma żadnej zadyszki ani nic... tylko skrypt zwalnia..
Na końcu pętli mam persisty i flush
Co jeszcze mogę zrobić?
Dodam że skrypt jest napisany w #symfony2 pod konsolą (command).
  • 16
@qwelukasz: Generalnie powinieneś pakować to w paczki (po powiedzmy 50 obiektów jeśli jeszcze tego nie robisz), a po flushu warto przeiterować po tych obiektach i zrobić na nich

$entityManager->detach($object);
Wtedy Garbage Collector będzie mógł od razu je zgarnąć i posprzątać, w innym przypadku siedzą w pamięci niepotrzebne obiekty.

edit: ewentualnie po flushu zrób $em->clear(); który #!$%@? wszystkie obiekty w EM
--env=prod


@DanioPL: ale gdzie to odpalic? Swój skrypt odpalam tak:
php app/console nazwa:metoda parametr. Na końcu mam dodać -e prod?

A obiekty to tak:
Dwa dodaję na początku, tzn robię persist.
A potem w pętli 5x persist i na końcu pętli flush. I tak przy każdej iteracji.

opcache dla konsoli masz uruchomiony


@DanioPL: Nie.
Dodać do config.yml ten wpis?

doctrine:
orm:
...
metadata_cache_driver: apc
...

Generalnie powinieneś
@qwelukasz: robić flusha i clear co 50 iterację, kodu nie chce mi się pisać w tym momencie, więc musisz sam sobie poradzić, co do opcache musisz go włączyć w konfiguracji PHP, a nie apki. Env prod na końcu w takiej postaci jak Ci napisałem
@qwelukasz: na devie system zbiera bardzo dużo informacji przydatnych do debugowania i za każdym razem przeładowuje konfiguracje, której nie #!$%@?. Zrób również php app/console cache:warmup --env=prod przed wykonaniem komendy. Znacznie przyspiesza całość aplikacji.
@qwelukasz: Tak się tego nie robi, uruchom sobie skrypt równolegle i zobacz jak zmienia się ETA. Jeżeli rozdzielisz to na osobne zadania razem z jakaś kolejka, to pozbędziesz się obecnych problemów a dodatkowo przyspieszysz pobieranie treści.
@qwelukasz:

Poniżej masz kawałek przykładowego kodziku w jaki sposób możesz uniknąć ładowania danych do arraya i iterowania później po tym. Tablice w PHP zjadają bardzo dużo pamięci, dopiero w PHP 7 będzie to znacznie zoptymalizowane. Ciężko mi się wypowiedzieć bo nie widzę tego co masz napisane. W każdym razie powyciągane (nie wiem skąd) obiekty ładujesz sobie do kolekcji, a jak już masz wszystko to robisz sobie

foreach($objectCollection->getIterator() as $object)
{
$em->persist($object);
@hajs86: ok załóżmy taki bardzo prosty przykład:
co w przypadku gdy mam np. ManyToOne i obiekty:
Dzień, TypDnia
$d1 = new TypDnia();
$d1->setName('Poniedzialek');

$d2 = new TypDnia();
$d2->setName('Wtorek');

$arr[1] = $d1;
$arr[2] = $d2;

I teraz iteruję dni miesiąca i chę wiedzieć jaki to dzień?

foreach($objectCollection->getIterator() as $object)
{
echo $arr[ $Dzien->getDayNumber() ]->getName();
}

W takim przypadku muszę encje TypDnia trzymać w tablicy, chyba że zrobię kolejną pętlę i będę
@qwelukasz: Nie bardzo łapię o co teraz ci chodzi. Masz problem z wydajnością skryptu. Z pewnością w PHP iterowanie po dużych arrayach nie należy do najwydajniejszych dlatego przedstawiłem ci szybszą opjcę z wykorzystaniem SplObjectStorage i generatora dostępnego od PHP 5.5. Popisz sobie różne opcje i sam wyciągaj wnioski, w googlach też sporo na ten temat znajdziesz. Tutaj się raczej nie dogadamy.
@hajs86: hmm, no o może inaczej.
Jeżeli mam kolekcję. Jak mogę z niej pobrać konkretny obiekt z pominięciem foreach?
Załóżmy że mam obiekt Miasto oraz obiekt NazwaMiasta

Obiekt Miasto posiada ID z NazwaMiasta.
W przypadku tablic zrobiłbym to tak:

$nazwy['1'] = $katowice;
$nazwy['2'] = $warszawa;

I wtedy z obiektu Miasto mogę się tak odwołać:
$id = Miasto->getIdMiasta

$nazwy[ $id ] da mi nazwę miasta.. a w przypadku kolekcji?