![]() |
![]() ![]() |
![]() |
![]() ![]()
Post
#1
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Witajcie,
nie do końca wiem jak w PHP narazić się na wyciek pamięci, ale chyba właśnie padłem jego ofiarą. Mam skrypt konsolowy, który czyta po kolei strony z zewnętrznego serwera i zawsze po około 40-50-ciu tysiącach iteracji otrzymuję błąd w stylu: Cytat PHP Fatal error: Allowed memory size of 536870912 bytes exhausted (tried to allocate 421888 bytes) in ... on line 36 A to mój kod (uprościłem dla przykładu):
Linia 36. to: Czy po kroku iteracji zawartość $html dalej jest trzymana w pamięci? Jakoś nie chce mi się w to wierzyć. Ten post edytował SmokAnalog 4.02.2018, 13:09:52 |
|
|
![]()
Post
#2
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
PHP to język interpretowany, on przetwarza pokolei, a na końcu zwraca Ci dopiero wynik, wiec gdzieś te informację musi w pamieć przechować, dodatkowo domyślnie masz ograniczenia zużycia pamieć dla skryptu, które zawsze można próbować sobie podnieść.
zrób to jakimś systemem kolejkowym najlepiej ![]() |
|
|
![]()
Post
#3
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Dzięki, ale to chyba nie jest odpowiedź na moje pytanie? Co ma do tego system kolejkowy? Poza tym to, że przetwarza po kolei nie znaczy, że też nie ma wewnętrznego zarządzania pamięcią?
|
|
|
![]()
Post
#4
|
|
Grupa: Zarejestrowani Postów: 460 Pomógł: 49 Dołączył: 5.06.2011 Ostrzeżenie: (0%) ![]() ![]() |
Czasami ograniczenia pamięci wkurzają. Np. niezajęta partycja swap, a komunikat, że brakuje pamięci. Z ciekawości: jakie jest tam ustawienie memory_limit w php.ini?
|
|
|
![]()
Post
#5
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
https://github.com/php/php-src/blob/master/...ard/file.c#L522 tutaj jest kod za to odpowiedzialny
![]() Jest zarządzie pamięcią robi malloc i gdzieś tam pewnie jest ta pamieć zwalniana ale niekoniecznie od razu. No system kolejkowy, żeby wrzucić te operacje na kolejkę i przetworzyć a nie robić to w pętli tak jak masz teraz |
|
|
![]()
Post
#6
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Wyciek pamięci, a wyczerpanie dozwolonego limitu zużycia pamięci dla skryptu to dwie różne kwestie. Zwróć uwagę na to, że nie podałeś warunku zakończenia pętli for, zatem nie dziw się, że mieli w nieskończoność aż dojdzie do limitu pamięci.
-------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#7
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
@darko tylko co ma do tego brak warunku? Ma mielić w nieskończoność i dobrze napisany kod nie powinien doprowadzić do wycieku nawet gdy mieli przez trylion lat. Twoim tokiem rozumowania to każda pierwsza lepsza gra komputerowa powinna wywoływać wyciek.
|
|
|
![]()
Post
#8
|
|
Grupa: Zarejestrowani Postów: 6 806 Pomógł: 1828 Dołączył: 11.03.2014 Ostrzeżenie: (0%) ![]() ![]() |
Coś się poprawia dodając unset($html) i/lub http://php.net/manual/en/function.gc-collect-cycles.php ?
Ten post edytował trueblue 4.02.2018, 15:36:43 -------------------- |
|
|
![]()
Post
#9
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
Ale zacznijmy od tego że PHP, nie koniecznie jest dobrze napisanym kodem, poza tym gry w PHP się nie pisze to zupełnie dwa rożne światy
![]() |
|
|
![]()
Post
#10
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Nie zrozumieliśmy się. Problemy ze zwalnianiem pamięci w pętlach w PHP są tak stare jak świat. Na podstawie tego fragmentu kodu trudno określić co dzieje się ze zmienną $html dalej i czy robisz tam jakiś unset czy nie. Użyj profilera, poświęć czas na analizę logu, poeksperymentuj z garbage collectorem. W sieci można znaleźć wiele tematów dotyczących problemów z pamięcią i używaniem takich funkcji jak json_decode, file_get_contents i funkcjami operującymi na xmlu. PHP generalnie średnio nadaje się do pisania rozwiązań działających na zasadzie demonów właśnie przez znane problemy ze zwalnianiem pamięci.
-------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#11
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Nie jest przypadkiem tak, że dla konkretnego adresu wczytywanie jego zawartości powoduje przekoreczenie pamięci? Może jest tam tak duża zawartość ze wczytanie jej do zmiennej w PHP powoduje przekoreczenie limitu. Ustal czy błąd powstaje każdorazowo dla tego samego adresu ($id).
|
|
|
![]()
Post
#12
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
@phpion Jestem pewien. Jedna strona nie ma 512 MB. Rozumiem, że podważasz zdanie kolegów wyżej?
@darko Nie wiem czy PHP się aż tak różni, żeby uniemożliwiać użycie pętli idących w tysiące iteracji. Zalicza się go jednak do języków ogólnego przeznaczenia. Świat PHP nie kończy się na requestach i response'ach. @trueblue Muszę właśnie zrobić taki test. Zmienię limit pamięci na malutki, np. 1 MB, dam unset i zobaczę. Do głowy przychodzi mi jeszcze jedna możliwość. Używam w tej pętli kilka razy preg_match z trzecim argumentem, na przykład: Może ten trzeci argument, podawany w końcu jako referencja, powoduje wyciek? Tak naprawdę nie jest powiedziane, że to właśnie zmienna $html wyciekła. To ona spowodowała przekroczenie limitu, ale być może zapchało go coś innego? Tylko że poza preg_match, zapytaniami do bazy i echo nic tam innego nie ma, a bez echo też występuje ten błąd. Ten post edytował SmokAnalog 4.02.2018, 17:04:17 |
|
|
![]()
Post
#13
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Do zmiennej $html wczytujesz ponad 500 Mb danych co powoduje przekroczenie pamięci. Żadne unsety tutaj nie pomogą bo sama zmienna zawiera w sobie zbyt wiele danych.
|
|
|
![]()
Post
#14
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Eee, jakim cudem wczytuję do zmiennej $html 500 mega?
![]() |
|
|
![]()
Post
#15
|
|
Grupa: Zarejestrowani Postów: 1 240 Pomógł: 278 Dołączył: 11.03.2008 Ostrzeżenie: (0%) ![]() ![]() |
memory_get_usage
Po prostu sprawdź w którym momencie ilość pamięci wzrasta. Może masz jakąś tablicę której nie czyścisz, może to jakiś wbudowany mechanizm PHP dla danej funkcji. Wywołaj tą funkcję po każdym "bloku", następnie w danym "bloku" (tym który zwiększa zużycie) po każdej linijce itp. Jak znajdziesz linijkę to już pewnie sobie poradzisz. Podawanie fragmentu kodu jest dobre w większości przypadków - ale nie tutaj, możesz pokazać całość. Pokazałeś tylko file_get_contents a na 99% przyczyna jest w innym miejscu. To, że w tej lini występuje błąd też nic nie mówi - jeżeli mamy 50 kb dostępnej pamięci, a file_get_contents zabiera tylko 5 kb pamięci, to chcemy się dowiedzieć skąd pochodzi reszta tj. 45 kb. A, że akurat została przekroczona w tym miejscu - to bez znaczenia. Ten post edytował markuz 4.02.2018, 21:22:28 -------------------- |
|
|
![]()
Post
#16
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Masz rację, że to nie dowód. Sam o tym napisałem powyżej. A co myślisz o koncepcji z preg_match?
|
|
|
![]()
Post
#17
|
|
Grupa: Zarejestrowani Postów: 1 240 Pomógł: 278 Dołączył: 11.03.2008 Ostrzeżenie: (0%) ![]() ![]() |
Nic nie myślę, po prostu to sprawdź tą funkcją
![]() -------------------- |
|
|
![]()
Post
#18
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Jasne. Sprawdzę jak dotrę do domu
![]() |
|
|
![]()
Post
#19
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Mój błąd, przeczytałem ze wczytujesz więcej niż 500Mb. Tak czy inaczej piszesz ze błąd dotyczy linii z file_get_contents wiec chyba w tym miejscu przekraczasz pamięć. Użyj podanej przez markuza funkcji badając zużycie pamięci w poszczególnych liniach/iteracjach. Teoretycznie przy każdej iteracji pamięć niekoniecznie powinna wzrastać bo jest to zależne od rozmiaru obrabianych danych. Ustal tez czy problem tyczy konkretnego $id czy pojawia sie losowo.
|
|
|
![]()
Post
#20
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Owszem, ale na logikę: to nie znaczy, że to ta linia powoduje wyciek. Ona przekracza, co jest zrozumiałe, bo potrzebuje jej najwięcej. Ale kumulować pamięć może cokolwiek imnego.
Dobra Panowie. Już wiem co powoduje wyciek. Przepraszam, że dopiero teraz to mówię, ale tak obsługuję wyjątki w tym skrypcie:
Ilekroć strona nie istnieje (404), mój file_get_contents wyrzuca wyjątek. Tak ma być, ale jest jeden problem. Każdy poprzedni $html jest zapisywany jako stack trace tego wyjątku. Zrobiłem test polegający na tym, że wypisuję ilość zużywanej pamięci i dodatkowo ustawiłem na sztywno numerek dla URL-a na taki, który zwraca 404. Pamięć rośnie wtedy jak szalona. W moim normalnym użyciu, tych 404 nie ma aż tak dużo, ale wystarczająco, by w końcu przepełnić pamięć. Jak mogę sprawić, by te wyjątki nie przechowywały całego stosu? Nie ukrywam, że najchętniej zostałbym przy wyjątkach zamiast klasycznych błędów. Próbowałem dać xdebug_disable();, ale nie istnieje u mnie taka funkcja. |
|
|
![]()
Post
#21
|
|
![]() Grupa: Zarejestrowani Postów: 8 068 Pomógł: 1414 Dołączył: 26.10.2005 Ostrzeżenie: (0%) ![]() ![]() |
Jeśli używasz PHP7 to w teorii powinno Ci samo wywalić Exception. Próbowałeś to wywalić?
|
|
|
![]()
Post
#22
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Wyrzuca stary,
|
|
|
![]()
Post
#23
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
Ciężko jest odtworzyć Twój błąd nawet z zastosowaniem Twojego skryptu do obsługi wyjątków rzuca po prostu mi ten FAIL bez stack trace
|
|
|
![]()
Post
#24
|
|
Grupa: Zarejestrowani Postów: 1 240 Pomógł: 278 Dołączył: 11.03.2008 Ostrzeżenie: (0%) ![]() ![]() |
Kod ? ~ php7.1 test.php FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 ? ~ php7.0 test.php FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 FAIL 2097152 7.2 nie mogę teraz zainstalować, także sprawdzę później. Ale już przy większej ilości interacji coś wzrasta: Kod FAIL 264 2097152 FAIL 265 2097152 FAIL 266 4194304 Ten post edytował markuz 5.02.2018, 22:51:21 -------------------- |
|
|
![]()
Post
#25
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Pobawiłem się trochę Twoim i moim przykładem. Wniosek jest taki, że memory_get_usage(true) u mnie też pokazuje stałą wartość, ale już memory_get_usage() nie.
|
|
|
![]()
Post
#26
|
|
Grupa: Zarejestrowani Postów: 1 240 Pomógł: 278 Dołączył: 11.03.2008 Ostrzeżenie: (0%) ![]() ![]() |
Bez wyjątków nie pobiera więcej pamięci:
Kod 789 2097152
790 2097152 791 2097152 792 2097152 793 2097152 794 2097152 795 2097152 796 2097152 797 2097152 -------------------- |
|
|
![]()
Post
#27
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
I to też jest bardzo ciekawa obserwacja. Masz jakiś pomysł jak to ugryźć? Ten projekt to nie jest sprawa życia i śmierci, ale bardzo mnie ciekawi ten problem i wolałbym zachować wyjątki. Jak nic nie wymyślimy, to zapytam na Stack Overflow.
|
|
|
![]()
Post
#28
|
|
Grupa: Zarejestrowani Postów: 1 240 Pomógł: 278 Dołączył: 11.03.2008 Ostrzeżenie: (0%) ![]() ![]() |
Nie mam pomysłów. Wrzuć link do stackoverflow jak zadasz pytanie
![]() -------------------- |
|
|
![]()
Post
#29
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Temat już wisi. Nie będę linkował, ale podzielę się odpowiedzią jak tylko się pojawi.
|
|
|
![]()
Post
#30
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
Kod FAIL
855 2097152 FAIL 856 2097152 FAIL 857 2097152 FAIL 858 2097152 FAIL 859 2097152 FAIL 860 2097152 FAIL 861 2097152 FAIL 862 2097152 FAIL 863 2097152 Ten post edytował com 6.02.2018, 19:16:23 |
|
|
![]()
Post
#31
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
@com zobacz, co pisaliśmy wyżej. Bez unset też będziesz miał stałą wartość.
|
|
|
![]()
Post
#32
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
SmokAnalog ale unset jest na Exception, nie ma stałej wartości przy 220(u mnie/266 u kolegi markuz) mamy już 2*2097152, potem 4*2097152 itd. Problem polega na tym, że PHP trzyma referencje do wszystkich poprzednich Exception na stosie i trzeba je wykasować to pamieć nie rośnie zobacz doleciałem do pozycji 863
![]() Ten post edytował com 6.02.2018, 19:36:37 |
|
|
![]()
Post
#33
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Chyba rzeczywiście jest coś w tym co mówisz, ale źle to argumentujesz. Zrobiłem testy i usunięcie unset nic nie zmienia. Jest za to jedno "ale" - różnica w ilości pamięci pojawia się, gdy użyjemy memory_get_usage() zamiast memory_get_usage(true). Tutaj rzeczywiście unset($e) powoduje, że pamięć nie rośnie, podczas gdy bez unset rośnie.
Pytanie jeszcze o co chodzi z tym parametrem w memory_get_usage, bo wg dokumentacji jest to: Cytat real_usage Set this to TRUE to get total memory allocated from system, including unused pages. If not set or FALSE only the used memory is reported. W praktyce ustawienie go na true nie uwzględnia wielkości stosu, więc albo im się coś popieprzyło, albo ja czegoś nie rozumiem. |
|
|
![]()
Post
#34
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
przy
Kod 582 366144 FAIL 583 366144 FAIL 584 366144 FAIL 585 366144 FAIL 586 366144 FAIL 587 366144 FAIL 588 366144 Ten parametr w zasadzie nic nie zmienia, tylko mamy trochę większe zużycie ale ono nie rośnie dzięki temu że kasujemy referencje do poprzedniego. Cytat It is because exceptions include a backtrace, containing all the arguments given to the error handling closure. The fifth argument of ErrorException given is $context, an array containing all local variables, including the previous $e. Cytat Pytanie jeszcze o co chodzi z tym parametrem w memory_get_usage, bo wg dokumentacji jest to: W źródle dokładnie to wygląda tak: Kod if (real_usage) {
return AG(mm_heap)->real_size; } else { size_t usage = AG(mm_heap)->size; return usage; } Ten post edytował com 6.02.2018, 20:05:26 |
|
|
![]()
Post
#35
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Ten parametr w zasadzie nic nie zmienia, tylko mamy trochę większe zużycie ale ono nie rośnie dzięki temu że kasujemy referencje do poprzedniego. Jak się dokładniej przyjrzałem, to ten parametr z true zwraca o wiele większą ilość pamięci (true: 2 MB, false: niecałe 400 KB). Daję Ci punkciki Pomógł, bo rzeczywiście naprowadziłeś mnie na rozwiązanie problemu, a właściwie udowodniłeś to, co sam podejrzewałem. No to teraz już wiem jak sprawić, żeby mój crawler się nie dławił ![]() |
|
|
![]()
Post
#36
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
|
|
|
![]()
Post
#37
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Dzisiaj całą noc chodził crawlerek bez żadnej zadyszki
![]() |
|
|
![]()
Post
#38
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
super
![]() ![]() |
|
|
![]()
Post
#39
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Cytat It is because exceptions include a backtrace, containing all the arguments given to the error handling closure. The fifth argument of ErrorException given is $context, an array containing all local variables, including the previous $e. Hmm... pół giga tekstu backtrace'u dla bieżącego i poprzedniego wyjątku + zawartość zmiennych lokalnych. To ile łącznie wyjątków zostało rzuconych? Ciężko w to uwierzyć, że to jest faktyczna przyczyna problemu. -------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#40
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Czy ja wiem czy takie dziwne?
Zrobiłem jeszcze jeden test:
Mam dane dla różnych liczb faili i w zależności czy unset był włączony czy nie:
Czyli przy stu failach, var_dump z usuniętym nadmiarem białych znaków ma 673 KB. Każdy fail dodaje do pamięci na przykład pełną informację o $_SERVER, a to swoje waży. Co więcej, w moich testach są tylko nieudane file_get_contents. Zauważyłem, że w pamięci nie ma wcale HTML-a z tych nieudanych, tylko właśnie z poprzedniej wartości - tej udanej. Czyli w moim teście HTML-a nie było wcale w pamięci. W kolejnym teście zrobiłem tak, że naprzemiennie występuje prawidłowy i nieprawidłowy URL. I tutaj uwaga! Przy braku unset i zaledwie 10-ciu failach, rozmiar pliku wzrósł z 72 KB do... 6 MB! Właśnie dlatego, że dla każdego wyjątku była doklejona poprzednia wartość $html. Wniosek: najlepszym rozwiązaniem wydaje się rzeczywiście unset($exception), ale unset($html) też w dużym stopniu pomaga. Ten pierwszy sprawia, że zużycie pamięci w ogóle nie rośnie z kolejnymi failami, a ten drugi sam z siebie zmniejsza znacznie pamięć zabieraną przez wyjątki, ale zużycie nadal rośnie i w końcu się przepełni. @darko jak widać ilość pamięci zabieranej przez wyjątki jest tu na tyle duża, że nie ma co wątpić. Przy setkach tysięcy iteracji to się niestety zsumuje do tych 500 MB, nawet z unset($html). Ten post edytował SmokAnalog 8.02.2018, 14:53:10 |
|
|
![]()
Post
#41
|
|
![]() Grupa: Zarejestrowani Postów: 3 034 Pomógł: 366 Dołączył: 24.05.2012 Ostrzeżenie: (0%) ![]() ![]() |
Ale jest, bo nie wywołany jest destruct na starym Exception wiec, gc nie może sprzątać, bo jak pamiętamy PHP zlicza referencje
![]() |
|
|
![]()
Post
#42
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Jeśli masz znaczną ilość faili, to może przed próbą pobrania zawartości strony odczytaj samą wartość nagłówka HTTP i sprawdzaj czy to nie 404. mam na myśli coś takiego, pobierasz tylko nagłówki odpowiedzi serwera i wyciągasz sam kod http odpowiedzi:
-------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#43
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
Darko, nie obraź się, ale wszystkie Twoje odpowiedzi w tym temacie (łącznie z powyższą) są idiotyczne. Sugerujesz teraz, żeby spowolnić cały crawler dwukrotnie tylko po to, żeby uniknąć wyjątku? Przecież wiadomo, że wąskim gardłem wszelkich webowych crawlerów jest czas odpowiedzi serwera zewnętrznego. Poczytaj ten temat i inne podobne tematy, żeby poznać konsolowe i crawlerowe zastosowanie PHP. Ubolewam nad tym, że przez całą noc crawluję zaledwie 20-30 tys. wyników, ale nieeee - spowolnię sobie to do 10-15 tys., żeby nie wyrzucać wyjątków. Yeah!
Jakbym już miał unikać wyjątków, to przecież mogę od razu użyć cURL-a, który wyjątków dla 404 nie wywala. Chciałem uprościć kod i nauczyć się czegoś więcej o zarządzaniu pamięcią w sytuacji wyrzucania wyjątków. Ten post edytował SmokAnalog 9.02.2018, 23:53:21 |
|
|
![]()
Post
#44
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
To teraz Ty się nie obraź, bo już mnie lekko irytujesz swoją impertynencją w tym i nie tylko w tym temacie. Najpierw sam sobie tworzysz wyimaginowany problem i wprowadzasz ludzi, którzy chcą się wspólnie zmóżdzyć z Tobą w błąd, nie podając pełnego kodu, a jedynie jakieś wyrywki. Pewnie. Domyślamy się wszyscy, że masz swój error handler... Patrz! unset zwalnia pamięć! Eureka! Następnie drążysz temat zarządzania pamięcią, na które to dość specyficzne w PHP zarządzanie nie masz totalnie żadnego wpływu i głową muru nie przebijesz, by na końcu określić czyjąś wypowiedź jako idiotyczną. Świetnie. Bawmy się tak dalej.
Użyj curla i nie płacz, że wolno działa, albo, że skrypt zżera za dużo pamięci. Przez podejście takich ludzi, jak Ty, o społeczności skupionej wokół języka PHP jeszcze długo będzie się mówić źle i tylko źle. Zamiast skupić się na użyteczności i przydatności kodu, a przede wszystkim na jego wartości biznesowej, lecisz na forum ze sztucznie stworzonym problemem, którego tak naprawdę nie ma. Założę się, że nawet nie raczyłeś sprawdzić curlowego rozwiązania, ale z góry zakładasz, że będzie działało znacznie wolniej. Poczytaj o curl_multi_init, curl_multi_exec, wykonywaniu jednoczesnym żądań korzystając z tzw. gniazd nieblokujących, asynchronicznie. Jakby to dobrze napisać, to ten Twój crawlerek będzie zapierdzielał jeszcze szybciej niż z kupą niepotrzebnych wyjątków i skopiowanym całym backtracem zupełnie niepotrzebnie. Jak znasz odrobinę języka C to polecam lekturę źródeł PHP, tam naprawdę więcej nauczysz się o zarządzaniu pamięcią, niż poprzez takie eksperymenty. Zresztą - nawet jeśli ten crawler będzie ciut wolniejszy, to chyba lepiej troszkę wolniej, ale niech w ogóle działa i nie wali błędami niż crawler, który po prostu nie działa... PHP jeszcze Cię wiele razy zaskoczy. Idiotyczne są takie pseudo problemy. Tyle z mojej strony, trzymaj się, buziaki, pozdrówki. ps. nie jesteś w stanie mnie obrazić. Ten post edytował darko 10.02.2018, 02:38:35 -------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#45
|
|
![]() Grupa: Zarejestrowani Postów: 1 707 Pomógł: 266 Dołączył: 3.07.2012 Skąd: Poznań Ostrzeżenie: (0%) ![]() ![]() |
No ciekawe jak przyśpieszysz w kodzie crawlera przysyłanie odpowiedzi ze źródła, na które nie masz wpływu. Coś tam Ci świta z zarządzaniem pamięci, ale sam się gubisz. Jeszcze przed chwilą mówiłeś, że PHP się nie nadaje do daemonów i crawlerów, co jest kompletną bzdurą.
Akurat unset w catch nie jest powszechnie znaną techniką, bo nie jest oczywistym faktem to co się dzieje z wyjątkami w pamięci. Lepiej być impertynenckim niż niekompetentnym i wypowiadać się w tematach, o których się nie ma pojęcia, zamiast grzecznie czekać na odpowiedź kogoś, kto się zna. A problem nie jest wyimaginowany. Bardzo często chce się zachować strukturę z wyjątkami i dobrze jest wiedzieć jak zaradzić zaśmiecaniu pamięci w pętli try..catch. Najpierw mówiłeś coś innego, teraz mówisz coś innego, więc grzecznie przyznaj się do błędu zamiast teraz udawać eksperta w tym temacie. |
|
|
![]()
Post
#46
|
|
![]() Grupa: Zarejestrowani Postów: 2 592 Pomógł: 445 Dołączył: 12.03.2007 Ostrzeżenie: (0%) ![]() ![]() |
Darko, nie oUbolewam nad tym, że przez całą noc crawluję zaledwie 20-30 tys. wyników, Jeśli to za mało to mam kilka propozycji * cURL zamiast file_get_contnets (w wielu wypadkach cURL jest szybsze, więcej rzeczy można ustawić) * curl_multi - aby zwielokrotnić ilość pobieranych zasobów * kilka procesów na raz Prosty przykład:
Test (obcięte wyniki do dwóch pierwszych i ostatnich)
Wersja na curl:
A bez curl_setopt($ch, CURLOPT_HEADER, 0); trwało porównywalnie do wersji z file_get_contents:
Wersja z curl_multi
Podsumowanie * file_get_contents: 1m8.822s * curl: 0m48.066s * curl_multi: 0m32.255s Ten post edytował vokiel 10.02.2018, 13:59:38 -------------------- |
|
|
![]()
Post
#47
|
|
![]() Grupa: Zarejestrowani Postów: 2 885 Pomógł: 463 Dołączył: 3.10.2009 Skąd: Wrocław Ostrzeżenie: (0%) ![]() ![]() |
Jeszcze przed chwilą mówiłeś, że PHP się nie nadaje do daemonów i crawlerów, co jest kompletną bzdurą. Najpierw mówiłeś coś innego, teraz mówisz coś innego, więc grzecznie przyznaj się do błędu zamiast teraz udawać eksperta w tym temacie. Błędu? Jakiego błędu? Ja podtrzymuję to, co napisałem. Do napisania wydajnego crawlera ludzie wybierają inne niż php narzędzia: perl, python, javę, a nawet basha czy node.js. Rozumiem, że Ty jesteś z tych, co uważają, że programowanie zaczyna się w momencie napisania pierwszej linii kodu. Dla mnie programowanie to najpierw dogłębna analiza problemu i dobranie optymalnego (czyt. najlepszego) narzędzia do danej sytuacji, a nie pisanie w tym, w czym wydaje Ci się, że umiesz to zrobić i jakoś to będzie. Jak widać, jakoś to nie będzie. Jakoś to nie jakość, a forum jest od rozwiązywania problemów, a nie od ich mnożenia. Vokiel już Ci podał na tacy kilka możliwych rozwiązań, ale pewnie i tak będziesz się upierał przy swoim, że po co, że na co tak itd. Kończę tę jałową przepychankę, bo pojawiają się z Twojej strony argumenty z półki ad personam, co nigdy dla poważnej rozmowy niczego dobrego nie wróżyło. Ponownie pozdrawiam Cię i mimo wszystko życzę Ci powodzenia i owocnej nauki. Miłego dnia. -------------------- Nie pomagam na pw, tylko forum.
|
|
|
![]()
Post
#48
|
|
![]() Grupa: Moderatorzy Postów: 6 072 Pomógł: 861 Dołączył: 10.12.2003 Skąd: Dąbrowa Górnicza ![]() |
Panowie, nie ma się co tak napinać. Każdy z Was wnosi konkrety do dyskusji nawet jeśli zdania są podzielone. Sam z ciekawością czytam wypowiedzi jednego i drugiego. Można się spierać ale trzymajmy poziom, osobiste wycieczki są daremne. Nie jesteście zapewne nastolatkami więc powinniście podejść do dyskusji na odpowiednim poziomie. Każda wypowiedź jest cenna i tego się trzymajmy. Żaden z Was chyba nie pisze po to żeby dogryźć drugiemu. Nie ma co być uszczypliwymi.
|
|
|
![]() ![]() |
![]() |
Wersja Lo-Fi | Aktualny czas: 25.07.2025 - 11:17 |