Witaj Gościu! ( Zaloguj | Rejestruj )

Forum PHP.pl

3 Stron V  < 1 2 3 >  
Reply to this topicStart new topic
> [PHP] Wyciek pamięci
Pyton_000
post 5.02.2018, 12:23:26
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ć?
Go to the top of the page
+Quote Post
SmokAnalog
post 5.02.2018, 12:30:49
Post #22





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Wyrzuca stary, dobry warning na PHP 7.2.
Go to the top of the page
+Quote Post
com
post 5.02.2018, 18:14:06
Post #23





Grupa: Zarejestrowani
Postów: 3 032
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
Go to the top of the page
+Quote Post
markuz
post 5.02.2018, 22:28:49
Post #24





Grupa: Zarejestrowani
Postów: 1 240
Pomógł: 278
Dołączył: 11.03.2008

Ostrzeżenie: (0%)
-----


  1. <?php
  2.  
  3. set_error_handler(function ($severity, $message, $file, $line) {
  4. if (!(error_reporting() & $severity)) {
  5. // This error code is not included in error_reporting
  6. return;
  7. }
  8.  
  9. throw new ErrorException($message, 0, $severity, $file, $line);
  10. });
  11.  
  12. while(true) {
  13. try {
  14. $content = file_get_contents('http://forum.php.pl/test.php');
  15. } catch (Exception $e) { echo "FAIL" . PHP_EOL; }
  16. echo memory_get_usage(true) . PHP_EOL;
  17. }


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


--------------------
Go to the top of the page
+Quote Post
SmokAnalog
post 5.02.2018, 22:53:35
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.
Go to the top of the page
+Quote Post
markuz
post 5.02.2018, 23:02:09
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:

  1. <?php
  2.  
  3. $n = 0;
  4.  
  5. while(true) {
  6. $content = @file_get_contents('http://forum.php.pl/test.php');
  7. echo $n++ . ' ' . memory_get_usage(true) . PHP_EOL;
  8. }


Kod
789 2097152
790 2097152
791 2097152
792 2097152
793 2097152
794 2097152
795 2097152
796 2097152
797 2097152


--------------------
Go to the top of the page
+Quote Post
SmokAnalog
post 5.02.2018, 23:07:50
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.
Go to the top of the page
+Quote Post
markuz
post 5.02.2018, 23:33:33
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 smile.gif


--------------------
Go to the top of the page
+Quote Post
SmokAnalog
post 6.02.2018, 00:36:13
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.
Go to the top of the page
+Quote Post
com
post 6.02.2018, 19:15:58
Post #30





Grupa: Zarejestrowani
Postów: 3 032
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


  1. <?php
  2. set_error_handler(function ($severity, $message, $file, $line) {
  3. if (!(error_reporting() & $severity)) {
  4. // This error code is not included in error_reporting
  5. return;
  6. }
  7.  
  8. throw new ErrorException($message, 0, $severity, $file, $line);
  9. });
  10.  
  11. $n = 0;
  12.  
  13. while (true) {
  14. try {
  15. $content = file_get_contents('http://forum.php.pl/test.php');
  16. } catch (Exception $e) {
  17. echo "FAIL" . PHP_EOL;
  18. unset($e);
  19. }
  20. echo $n++ . ' ' . memory_get_usage(true) . PHP_EOL;
  21. }

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
Go to the top of the page
+Quote Post
SmokAnalog
post 6.02.2018, 19:23:01
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ść.
Go to the top of the page
+Quote Post
com
post 6.02.2018, 19:30:52
Post #32





Grupa: Zarejestrowani
Postów: 3 032
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 wink.gif

Ten post edytował com 6.02.2018, 19:36:37
Go to the top of the page
+Quote Post
SmokAnalog
post 6.02.2018, 19:39:51
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.
Go to the top of the page
+Quote Post
com
post 6.02.2018, 19:56:49
Post #34





Grupa: Zarejestrowani
Postów: 3 032
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


przy
  1. <?php
  2. set_error_handler(function ($severity, $message, $file, $line) {
  3. if (!(error_reporting() & $severity)) {
  4. // This error code is not included in error_reporting
  5. return;
  6. }
  7.  
  8. throw new ErrorException($message, 0, $severity, $file, $line);
  9. });
  10.  
  11. $n = 0;
  12.  
  13. while (true) {
  14. try {
  15. $content = file_get_contents('http://forum.php.pl/test.php');
  16. } catch (Exception $e) {
  17. echo "FAIL" . PHP_EOL;
  18. unset($e);
  19. }
  20. echo $n++ . ' ' . memory_get_usage() . PHP_EOL;
  21. }


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
Go to the top of the page
+Quote Post
SmokAnalog
post 6.02.2018, 20:10:33
Post #35





Grupa: Zarejestrowani
Postów: 1 707
Pomógł: 266
Dołączył: 3.07.2012
Skąd: Poznań

Ostrzeżenie: (0%)
-----


Cytat(com @ 6.02.2018, 19:56:49 ) *
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ł biggrin.gif
Go to the top of the page
+Quote Post
com
post 6.02.2018, 20:15:45
Post #36





Grupa: Zarejestrowani
Postów: 3 032
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


ha faktycznie ślepy jestem 2097152 > 366144 biggrin.gif No tak najistotniejsze jest pozbyć się starego $e biggrin.gif

Twórcy PHP twierdza, że nie jest to bug biggrin.gif
Wszytko przez to, że Exception ma taka metodę:
  1. $e->getPrevious();


Ten post edytował com 6.02.2018, 20:22:22
Go to the top of the page
+Quote Post
SmokAnalog
post 7.02.2018, 13:30:13
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 smile.gif
Go to the top of the page
+Quote Post
com
post 7.02.2018, 21:12:53
Post #38





Grupa: Zarejestrowani
Postów: 3 032
Pomógł: 366
Dołączył: 24.05.2012

Ostrzeżenie: (0%)
-----


super biggrin.gif ciekawe co tam crawlujesz tongue.gif
Go to the top of the page
+Quote Post
darko
post 8.02.2018, 11:30:29
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.
Go to the top of the page
+Quote Post
SmokAnalog
post 8.02.2018, 14:48:23
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:

  1. if ($fails === 100) {
  2. var_dump(get_defined_vars());
  3. $dump = preg_replace('# {2,}#', ' ', str_replace(PHP_EOL, ' ', ob_get_clean()));
  4. file_put_contents($fails.'.txt', $dump);
  5. }


Mam dane dla różnych liczb faili i w zależności czy unset był włączony czy nie:

  • 1 fail, włączony unset: 6 KB
  • 10 faili, włączony unset: 6 KB
  • 100 faili, włączony unset: 6 KB
  • 1 fail, wyłączony unset: 12 KB
  • 10 faili, wyłączony unset: 72 KB
  • 100 faili, wyłączony unset: 673 KB


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
Go to the top of the page
+Quote Post

3 Stron V  < 1 2 3 >
Reply to this topicStart new topic
1 Użytkowników czyta ten temat (1 Gości i 0 Anonimowych użytkowników)
0 Zarejestrowanych:

 



RSS Wersja Lo-Fi Aktualny czas: 28.03.2024 - 15:51