Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: Generowanie pdf
Forum PHP.pl > Forum > PHP
JoShiMa
Mam do wygenerowania dość duży dokument pdf. Sa to właściwie same tabelki a dokument składa się z kilkudziesięciu stron. Sprawdziłam FPDF i TCPDF i generowałam zawartość używając głównie metody Cell(), jednak obie klasy mają ten sam feler. Nie kończą roboty z powodu przekroczenia limitu pamięci. W przypadku TCPDF można użyć cache, ale tu dla odmiany mam przekroczenie czasu. Macie jakieś pomysły. Może jakaś inna klasa, albo jakiś trick?
!*!
To zwiększ ten limit w php.ini lub
  1. ini_set('memory_limit', 'wartosc');


lub reguły .htaccess
tehaha
Ciężko poradzić coś skoro nie wiadomo ile to jest "dość duży dokument" oraz nie wiadomo na jakim serwerze to odpalasz. Na początek warto spróbować zwiększyć parametry "max_execution_time" oraz "memory_limit" w pliku ini (jeżeli masz dostęp) lub funkcją ini_set() (o ile nie jest zablokowana).

Ogólnie nie powinno być problemu z wygenerowaniem pliku PDF z setkami stron, więc być może problem leży w skrypcie, który generuje treść, może najpierw wygeneruj treść, a potem odzielnie wygeneruj plik pdf. Najlepiej zacznij też od czegoś prostego, żeby lepiej zdiagnozować gdzie leży problem. Np. spróbuj wygenerować tak samo duży plik pdf ale z prostą treścią lub nawet pusty, albo sprawdź ile stron możesz wygenerować skutecznie bez błędu. W każdym bądź razie problem leży raczej w spobie generowania treści, a nie w bibliotekach do generowania, zakładając oczywiście, że jest to przeprowadzane na sensownym hostingu.

W ostateczności próbowałbym wygenerować kilka plików pdf i potem je złączyć, ale to już jako absolutna ostateczność.
JoShiMa
Cytat(!*! @ 28.07.2012, 16:25:54 ) *
To zwiększ ten limit w php.ini lub set_time_limit

lub reguły .htaccess

A jeśli serwer na top nie zezwala?
!*!
To albo rybki, albo akwarium. Serwer zmienia/modernizuje się względem zapotrzebowania oprogramowania.
JoShiMa
Cytat(tehaha @ 28.07.2012, 16:33:03 ) *
Ciężko poradzić coś skoro nie wiadomo ile to jest "dość duży dokument"


No na przykład taki:

Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 2656 bytes)
!*!
A to w ogóle jest darmowy serwer? Jeśli nie, to podaj nazwę tego hostingu dla potomnych, aby omijać go szerokim łukiem. Takie zmiany powinny być możliwe, jeśli nie bezpośrednio ze skryptu/panelu to po kontakcie z administracją.
JoShiMa
Cytat(!*! @ 28.07.2012, 17:31:18 ) *
A to w ogóle jest darmowy serwer? Jeśli nie, to podaj nazwę tego hostingu dla potomnych, aby omijać go szerokim łukiem. Takie zmiany powinny być możliwe, jeśli nie bezpośrednio ze skryptu/panelu to po kontakcie z administracją.

Jeśli nie potrafisz podpowiedzieć czegoś konstruktywnie to nie zaśmiecaj wątku. Ja tam nie lubię rozrzutności jeśli chodzi o zajętość pamięci i czas wykonywania skryptu i interesuje mnie jak odchudzić skrypt, jeśli to możliwe (wierzę, że tak) a nie jak mu przydzielić więcej pamięci.

Wiem, że są ludzie, którzy swoją karierę z kompem zaczynali w czasach, gdy wypasionych komputerów i wydaje im się, że to normalne, że programy są zasobożerne. Ja zaczynałam, gdy każdy bajt był na wagę złota (tylko w innym języku programowałam, bo o PHP to w PL jeszcze nikt nie słyszał, o internecie też) i każdy szanujący się programista umiał je oszczędzać. Teraz byle komórka ma lepszy procesor niż komputer na którym się uczyłam, ale to nie znaczy, że należy szastać zasobami bez wcześniejszego sprawdzenia czy nie da się czegoś jednak zoptymalizować.

Tak więc rozmawiajmy o możliwej optymalizacji takiego skryptu.
!*!
Trudno rozmawiać o optymalizacji czegokolwiek, gdy nie zna się szczegółów. Niczego konkretnego nie podałeś, prócz informacji że nie możesz niczego zmienić na serwerze. Optymalizacja skryptu jest możliwa, ale skoro przekraczasz jakieś limity to oczywiste że nie zmienisz tego nie wiadomo jak, serwery i jego zasoby nie są z gumy.
JoShiMa
Cytat(!*! @ 28.07.2012, 20:26:05 ) *
Trudno rozmawiać o optymalizacji czegokolwiek, gdy nie zna się szczegółów.

Dlatego podałam nazwy klas z których próbowałam korzystać i liczę na wypowiedzi osób, które z tymi klasami pracowały, albo znają inne, mniej zasobożerne klasy do generowania pdfów.
irmidjusz
Nie znam tych klas, które wymieniłaś, korzystałem jedynie z mPdf, ale nigdy nie generowałem nim tak dużych dokumentów.
A próbowałaś tego: http://www.phplivedocx.org/articles/pdf-ge...zend-framework/ ? smile.gif
d3ut3r
Jak już wspomniano ciężko coś napisać bez znajomości hostingu. Generalnie raczej nie liczyłbym na zoptymalizowanie klas. Można za to spróbować:

1. Generować po 1 stronie a później jeżeli jest możliwośc użycia np narzędzia gs połączyć je w 1 plik.
2. Skorzystać w ogóle tylko z narzędzia zewnętrznego a wywoływać je z PHP (htmldoc o ile mnie pamięć nie myli).
3. Dogadać się z adminem biggrin.gif
JoShiMa
Cytat(irmidjusz @ 29.07.2012, 01:17:07 ) *
Nie znam tych klas, które wymieniłaś, korzystałem jedynie z mPdf, ale nigdy nie generowałem nim tak dużych dokumentów.
A próbowałaś tego: http://www.phplivedocx.org/articles/pdf-ge...zend-framework/ ? smile.gif

A uruchamianie frameworka do wygenerowania jednego dokumentu będzie mniej pamięciożerne niż napisanie niewielkiego skryptu "z palca"? Wczoraj sprawdziłam, że nim zacznie się generować pierwsza strona już mam zajętość pamięci 12320768 wcześniej, samo dołączenie klasy tcpdf powoduje zajęcie na poziomie 8388608. W między czasie sa pobierane z pliku i przetwarzane dane na podstawie których generują się później te tabele w dokumencie. I to powoduje zajęcie około 4000000 a samo wygenerowanie dokumentu powoduje przekroczenie ilości jaką wcześniej podałam. Generowanie dokumentu pdh w tcpdf odbywa się poprzez wygenerowanie jego treści w postaci stringa. W tym wypadku jest on bardzo długi.
!*!
Nadal się upierasz przy swoim.
Nie chodziło mi o nazwy klasy, bo te same w sobie już są zoptymalizowane, może je źle wykorzystujesz? Pokaż kod.

Jeśli nie możesz zmienić czy umieścić w skryptach tak prostych rzeczy do zmiany czasu i pamięci, to nie licz że w ogóle da się coś zrobić, bo zakładam że nawet poleceń cmd nie możesz odpalić.
skowron-line
Tak jak @d3ut3r napisał jeżeli dane sie nie zmieniajaa zbyt często to dlaczego nie generować 5 tabelek osobno a jak ktoś będzie chciał całość to połączysz pliki, mpdf ma taką możliwość.

Możesz zrobić tak
- trzymasz 5 plików z tabelkami
- ktoś zmienai dane z 1 tabeliki po updacie / insercie kasujesz plik
- ktoś chce wygenerować cały raport (5 tabelek)
- sprawdzasz czy dana tabelka ma swój plik raportu jak ma to łaczysz jak nie to generujesz

i takim sposobem nie utkniesz na generowaniu wielu stron.

JoShiMa
Cytat(skowron-line @ 29.07.2012, 11:06:42 ) *
Tak jak @d3ut3r napisał jeżeli dane sie nie zmieniajaa zbyt często to dlaczego nie generować 5 tabelek osobno a jak ktoś będzie chciał całość to połączysz pliki, mpdf ma taką możliwość.

Bo nie ja o tym decyduję :/
tehaha
Jak mamy Ci pomóc skoro nie podajesz żadnych konkretnych informacji, najlepiej:

1. pokaż skrypt
2. napisz ile stron pliku pdf generujesz
3. powiedz jaki masz hosting do dyspozycji.

Z tego co mi się wydaje to nie biblioteki są tutaj problemem tylko proces generowania treści, którą chcesz umieścić w pdf'ie, bo te bibliotekai są z powodzeniem stosowane do generowanie plików z setkami stron i nie sprawia to problemów, sam też generowałem pilki pdf na kilkadzisiąt stron, nawet na tanich hostingach współdzielonych i problemu nie było. Więc wina leży raczej w skrypcie, no chyba, że postawiłaś to na jakimś darmowym lub bardzo kiepskim hostingu.
webdice
Cytat(!*! @ 28.07.2012, 21:26:05 ) *
Trudno rozmawiać o optymalizacji czegokolwiek, gdy nie zna się szczegółów. Niczego konkretnego nie podałeś, prócz informacji że nie możesz niczego zmienić na serwerze. (...)


Podała informacje o dostępnej ilości pamięci, o wykorzystywanej bibliotece i funkcji z jakiej korzysta. Co ma Ci jeszcze napisać? Że wykonuje X razy funkcje Cell i to stanowi problem?

Cytat(d3ut3r @ 29.07.2012, 06:04:00 ) *
Jak już wspomniano ciężko coś napisać bez znajomości hostingu. (...)


Jakie znaczenie ma hosting? Ma dostęp do określonej ilości pamięci (wcale nie małej), a jaki to jest serwer, nie ma kompletnie żadnego znaczenia.

Cytat(!*! @ 29.07.2012, 11:24:16 ) *
Jeśli nie możesz zmienić czy umieścić w skryptach tak prostych rzeczy do zmiany czasu i pamięci, to nie licz że w ogóle da się coś zrobić, bo zakładam że nawet poleceń cmd nie możesz odpalić.


Daruj sobie tego typu komentarze bo zrobię Ci miesięczną przerwę w pisaniu na forum.

Co do samego tematu, spróbuj może skorzystać z funkcji pdf_*. Jeśli dokument nie jest bardzo skomplikowany, nie powinnaś mieć problemu z jego wygenerowaniem.
!*!
Cytat
Podała informacje o dostępnej ilości pamięci, o wykorzystywanej bibliotece i funkcji z jakiej korzysta. Co ma Ci jeszcze napisać? Że wykonuje X razy funkcje Cell i to stanowi problem?

Cytat
Daruj sobie tego typu komentarze bo zrobię Ci miesięczną przerwę w pisaniu na forum.


Ochłoń. Jak niby chciałbyś to zoptymalizować? Jakoś nie widzę tu fragmentów kodów, co z tego że podała klasy, jak i wykorzystanie może być różne i nieprawidłowe. Najprostszy i najszybszy sposób to właśnie zmiana tych ustawień, ale skoro Jej hosting tego nie umożliwia, to trudno jest to zrobić chociażby z poziomu tych klas. Jak niby chciałbyś to przeskoczyć?
Hosting jest ważny, bo można sprawdzić jakie opcje posiada i według nich działać np. przenieść to poza PHP.
JoShiMa
Bardzo dużo pamięci (czego należało oczekiwać) zajmuje mi wielowymiarowa tablica z danymi pobranymi z pliku, które następnie muszą zostać zaprezentowane w tym pdfie. Niestety dane czyli około 2000 linii muszę najpierw wczytać z pliku CSV, następnie posortować i dopiero wtedy zaprezentować więc nie da się wczytywać po linii i od razy w locie wrzucać do pdfa. I takie pytanie mi się nasunęło. Jaski wpływ na zajętość pamięci mają klucze tablic. To znaczy czy użycie w charakterze kluczy dość długich stringów jest bardzo pamięciożerne?
sazian
Cytat(JoShiMa @ 29.07.2012, 20:55:05 ) *
Niestety dane czyli około 2000 linii muszę najpierw wczytać z pliku CSV, następnie posortować i dopiero wtedy zaprezentować więc nie da się wczytywać po linii i od razy w locie wrzucać do pdfa.


nasuwają mi się dwie propozycję.

1)posortuj ten plik i zrób z nim co zrobić musisz.
2)zapisz nowy plik(jako cache)
3)wywal wszystkie niepotrzebne zmienne (unset), wiem że php sam sprząta ale można mu pomóc
4)wczytuj cache po jednej linij i dodawaj do pdf'a - pamiętaj o sprzątaniu

propozycja druga

plik z klasą tcpdf ma około 30000 linij a co za tym idzie to musi zżerać zasoby. Spróbuj wywalić fragmenty kodu których na pewno nie użyjesz. Np funkcję związane z obsługą grafiki SVG to ponad 1700 linij - tyle znalazłem "na szybko" i myślę że można je spokojnie wywalić
tehaha
Cytat
Niestety dane czyli około 2000 linii muszę najpierw wczytać z pliku CSV, następnie posortować i dopiero wtedy zaprezentować więc nie da się wczytywać po linii i od razy w locie wrzucać do pdfa.

Więc spróbuj rozbić ten proces na etapy. Najpierw obróbka danych i zapis do tymczasowego pliku lub bazy, a potem oddzielnie już tylko proste pobranie przygotowanych danych i generowanie dokumentu.
mheki
Piszesz, że używałeś TCPDF i metody Cell().
Może warto zastanowić się nad wydzieleniem osobnej warstwy widoku i najpierw generować kod html, a następnie przekazywać go do metody writeHTML()?
Tworzyłem tak kilkustronicowe strony z tabelkami i wszystko grało.
JoShiMa
U mnie to będzie raczej bliżej 70 stron :/ no ale jest to do przemyślenia.
lukaskolista
Cytat
Bardzo dużo pamięci (czego należało oczekiwać) zajmuje mi wielowymiarowa tablica z danymi pobranymi z pliku, które następnie muszą zostać zaprezentowane w tym pdfie. Niestety dane czyli około 2000 linii muszę

eee... zakladajac, ze 1 linia ma 1000 znakow wychodzi, ze calosc ma 1,9MB - to nie tak duzo. Poza tym sortowac mozna trzymajac w pamieci tylko 2 linie pliku (chocby babelkowo...), oszczedzisz w ten sposob pamiec, ale ucierpi na tym szybkosc wykonywania.

Niestety wszelkie moduly do pdf, xls itp. sa pamieciozerne, pamietam jak wygenerowanie xls zajelo 6GB pamieci, gdzie plik wyjsciowy wazyl zaledwie 2MB... To wszystko wina tych klas, analizowalem struktore takiej klasy i pod wzgledem optymalizacji jest fatalnie.
JoShiMa
Może rzeczywiście nie pozostaje mi nic innego jak odchudzić klasę wywalając zbędne funkcje. TCPDF ma prawie 30 tys linii kodu.
irmidjusz
eee a co to pomoże? Przecież te fragmenty kodu, które wyrzucisz, nie wykonują się, więc to nie one są odpowiedzialne za skonsumowanie kilkudziesięciu - czy ile tam masz na serwerze - MB pamięci...
30k linii kodu? Gdyby w każdej było 120 znaków instrukcji, to daje razem raptem 3,43 MB plik. Dużo nie zaoszczędzisz.
!*!
Cytat(irmidjusz @ 31.07.2012, 17:49:27 ) *
eee a co to pomoże? Przecież te fragmenty kodu, które wyrzucisz, nie wykonują się, więc to nie one są odpowiedzialne za skonsumowanie kilkudziesięciu - czy ile tam masz na serwerze - MB pamięci...
30k linii kodu? Gdyby w każdej było 120 znaków instrukcji, to daje razem raptem 3,43 MB plik. Dużo nie zaoszczędzisz.


Są ludzie co wierzą że parser nie wyrabia przy interpretacji takich pokaźnych ilości.
JoShiMa
Cytat(irmidjusz @ 31.07.2012, 16:49:27 ) *
eee a co to pomoże?

To już Ci mówię co to pomoże. W momencie samego dołączenia klasy bez wywołania żadnego objektu mam zajętość pamięci na poziomie 8388608 a to dopieto pierwsza linijka mojego kodu. Po odchudzeniu klasy o kilka tysięcy linii kodu dołączenie zajętość pamięci spada do 7077888 Nie wydaje Ci się całkiem spore to Twoje 'nic'?

Cytat(irmidjusz @ 31.07.2012, 16:49:27 ) *
Przecież te fragmenty kodu, które wyrzucisz, nie wykonują się, więc to nie one są odpowiedzialne za skonsumowanie kilkudziesięciu - czy ile tam masz na serwerze - MB pamięci...

Ale jednak trochę konsumują, nie sądzisz? To może być ten grosz, którego brakuje tongue.gif
tehaha
nawet jeśli to zadziała to nie jest to rozwiązanie problemu, a jedynie jego ukrycie, nie możesz tak na styk zagospodarować pamięci, bo jak się okaże, że trzeba wygenerować o 5 stron więcej, albo serwer będzie obciążony to znowu się wszystko sypnie i co wtedy? Znowu będziesz patrzeć co tam jeszcz można usunąć? Skoro pamięci jest sporo, bo z tego co piszesz masz 128 dostępne, a stron generujesz nie wiele po jak pisałaś około 70, to wina leży w skrypcie, obróbka danych jest zbyt pamięciożerna i trzeba by ją rozbić na etapy.

ps. ta różnica co podałaś to trochę ponad 1MB, więc w skali 128 dostępnych MB to tyle co nic
Niktoś
Cytat
Ale jednak trochę konsumują, nie sądzisz? To może być ten grosz, którego brakuje.

To może wynikać z konfiguracji serwera-Cachowanie plików statycznych.Z drugiej strony-odchudzanie obojętne jakiego pliku ze zbędnego kodu ma bardzo duże znaczenie przy szybkości jego wykonywania się(chodzi tutaj o przeskoki z linii np.1 do linii n-parseser musi analizować każdą linię).

Propozycje tutaj padły.
Rozbić 70 stronicowy pdf'owy tekst na strony.
Zapisywać 1 stronicowy dokument pdf- zwolnić pamięć.
Otworzyć ten dokument pdf do edycji dopisać drugą stronę-zwolnić pamięć.
I tak aż do 70 stron.

Można zrobić cykle 2-3 stronicowe. W zależności ile pamięci miałoby to zużyć.
irmidjusz
I można też użyć usługi LiveDocx, np. z pomocą ZF http://www.phplivedocx.org/articles/pdf-ge...zend-framework/ lub w inny sposób, jak kto chce, ale z wykorzystaniem ZF jest to bardzo proste (przykład w podanym artykule). Aha, i nie wymaga to odpalenia frameworka smile.gif
Aczkolwiek sposób pracy z LiveDocx jest dość specyficzny i nie każdemu taka forma przypadnie do gustu.
JoShiMa
Cytat(tehaha @ 31.07.2012, 17:40:43 ) *
nawet jeśli to zadziała to nie jest to rozwiązanie problemu, a jedynie jego ukrycie, nie możesz tak na styk zagospodarować pamięci

Wiem. Pokazuję tylko, że wielkość klasy ma jednak pewne znaczenie. Sama jestem przeciwna tworzeniu takich napuchniętych tworów.

Cytat(tehaha @ 31.07.2012, 17:40:43 ) *
Skoro pamięci jest sporo, bo z tego co piszesz masz 128 dostępne, a stron generujesz nie wiele po jak pisałaś około 70, to wina leży w skrypcie, obróbka danych jest zbyt pamięciożerna i trzeba by ją rozbić na etapy.

Ale to już wiem i z tym się zgadzam smile.gif Na przykład zwolnienie całej tej ogromnej tablicy danych nim skrypt przystąpi do ostatecznego generowania pdfa. Bo wyobraź sobie, po obrobieniu całej tej tablicy i wygenerowaniu tych 70 stron tabelek zajętość pamięci jest na poziomie 43 MB. Po zwolnieniu tablicy z danymi niewiele poniżej 40 MB. Co pożera resztę, że się wyczerpuje?

@Niktoś nie bardzo rozumiem jak z poziomu php miałabym dopisywac do pdfa?

sazian
@JoShiMa tak z czystej ciekawości, czy odchudzanie pomogło ?
Niktoś
Cytat
@Niktoś nie bardzo rozumiem jak z poziomu php miałabym dopisywac do pdfa?

Jak zapisujesz coś jako plik pdf to równie dobrze możesz go odczytać, nadpisać lub usunąć.
Tak więc otwierasz zapisany wcześniej dokument pdf (jego ostatnią stronę o ile to możliwe) do edycji i dopisujesz kolejną stronę i zapisujesz.
JoShiMa
Cytat(sazian @ 1.08.2012, 22:06:15 ) *
@JoShiMa tak z czystej ciekawości, czy odchudzanie pomogło ?

Na lokalnym serwerze pomogło na testowym już niestety nie. Problem jest chyba z wielkością pliku finalnego. Jakieś specyficzne ustawienia serwera.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.