Co powoduje komunikat „Nie można przydzielić pamięci dla puli” w PHP?

133

Czasami napotykam limit alokacji pamięci serwera, szczególnie w przypadku rozdętej aplikacji, takiej jak Wordpress, ale nigdy nie spotkałem się z komunikatem „Nie można przydzielić pamięci dla puli” i nie miałem problemów ze śledzeniem jakichkolwiek informacji.

Czy ktokolwiek wie, co to znaczy? Próbowałem zwiększyć memory_limitbez powodzenia. Nie dokonałem też żadnych istotnych zmian w aplikacji. Jednego dnia nie było problemu, następnego trafiłem na ten błąd.

jonathanatx
źródło

Odpowiedzi:

90

Prawdopodobnie ma to związek z APC.

W przypadku osób mających ten problem określ ustawienia .ini. W szczególności twoje ustawienie apc.mmap_file_mask.

W przypadku mmapa opartego na plikach powinien być ustawiony na coś takiego:

apc.mmap_file_mask=/tmp/apc.XXXXXX

Aby wykonać mmap bezpośrednio z / dev / zero, użyj:

apc.mmap_file_mask=/dev/zero

Dla zgodnego z POSIX mmapa wspieranego pamięcią współdzieloną, użyj:

apc.mmap_file_mask=/apc.shm.XXXXXX
Frankie
źródło
Dzięki! To jest dokładnie ten link, którego szukałem. Doceń pomoc!
jonathanatx
2
Odkryłem, że te zmiany nie rozwiązują problemu, ponieważ komentarze w połączonym wątku również dokumentują ...
Jonathan Day,
3
Więcej informacji na temat tego ustawienia APC: php.net/apc.configuration#ini.apc.mmap-file-mask
mikeytown2
2
W moim przypadku musiałem zmienić plik z kopii zapasowej na zgodny z POSIX, aby pozbyć się błędu.
Attila Fulop
4
Nie rozumiem, jak ta odpowiedź rozwiązuje problem. Czy błąd występuje, gdy file_masknie jest jedną z tych wartości? Jeśli mam jedną z tych wartości i otrzymuję błąd, czy muszę zmienić ją na inną? Który?
Jeff,
125

Użycie TTL równej 0 oznacza, że ​​APC opróżni całą pamięć podręczną, gdy zabraknie jej pamięci. Błąd już się nie pojawia, ale sprawia, że ​​APC jest znacznie mniej wydajne. To bez ryzyka, bez kłopotów, decyzja „Nie chcę wykonywać swojej pracy”. APC nie jest przeznaczone do tego celu. Powinieneś wybrać wystarczająco wysoki TTL, aby najczęściej odwiedzane strony nie straciły ważności. Najlepiej jest zapewnić wystarczającą ilość pamięci, aby firma APC nie musiała opróżniać pamięci podręcznej.

Po prostu przeczytaj instrukcję, aby zrozumieć, w jaki sposób używany jest ttl: http://www.php.net/manual/en/apc.configuration.php#ini.apc.ttl

Rozwiązaniem jest zwiększenie pamięci przydzielonej APC. Zrób to, zwiększając apc.shm_size.

Jeśli APC jest skompilowane do korzystania z pamięci segmentów współdzielonych, system operacyjny będzie ograniczony. Wpisz to polecenie, aby zobaczyć limit systemu dla każdego segmentu:

sysctl -a | grep -E "shmall|shmmax"

Aby zaalokować więcej pamięci, musisz zwiększyć liczbę segmentów za pomocą parametru apc.shm_segments.

Jeśli APC używa pamięci mmap, nie masz ograniczeń. Ilość pamięci jest nadal definiowana przez tę samą opcję apc.shm_size.

Jeśli na serwerze nie ma wystarczającej ilości pamięci, użyj opcji filtrów, aby zapobiec buforowaniu rzadziej używanych plików php.

Ale nigdy nie używaj TTL równego 0.

Jak powiedział c33s, użyj apc.php, aby sprawdzić konfigurację. Skopiuj plik z pakietu apc do folderu internetowego i wskaż go przeglądarce. Zobaczysz, co jest naprawdę przydzielone i jak jest używane. Wykresy muszą pozostać stabilne po godzinach, jeśli całkowicie zmieniają się przy każdym odświeżaniu, oznacza to, że konfiguracja jest nieprawidłowa (APC przepłukuje wszystko). Przydziel o 20% więcej pamięci RAM niż to, czego naprawdę używa APC jako margines bezpieczeństwa i sprawdzaj to regularnie.

Domyślne zezwolenie tylko na 32 MB jest absurdalnie niskie. PHP zostało zaprojektowane, gdy serwery miały 64 MB, a większość skryptów korzystała z jednego pliku php na stronę. Obecnie rozwiązania takie jak Magento wymagają ponad 10 tys. Plików (~ 60 MB w APC). Powinieneś zostawić wystarczającą ilość pamięci, aby większość plików php była zawsze buforowana. To nie jest marnotrawstwo, bardziej wydajne jest trzymanie opcode w pamięci RAM niż posiadanie odpowiedniego surowego php w pamięci podręcznej pliku. Obecnie możemy znaleźć serwery dedykowane z 24 Gb pamięci za jedyne 80 USD / miesiąc, więc nie wahaj się pozwolić kilka GB na APC. Umieściłem 2 GB z 24 GB na serwerze obsługującym sklepy 5Magento i ~ 40 stron internetowych wordpress, APC używa 1,2 GB. Policz 64 MB na instalację Magento, 40 MB na Wordpress z kilkoma wtyczkami.

Ponadto, jeśli masz strony internetowe do tworzenia programów na tym samym serwerze. Wyklucz je z pamięci podręcznej.

bokan
źródło
2
To! Używam Wordpress i 32M to po prostu za mało. Podwyższone do 64 mln, a teraz jasne. Sprawdź ludzi apc.php!
Dave Drager
Dobra odpowiedź! +1 dzięki.
Kostanos
Aby zwiększyć do 64 MB, musisz dodać apc.shm_size = 64, a nie apc.shm_size = 64M (większość przykładów, które widziałem, miała na końcu M) Nie działa na mojej wersji apc (v3.1.3p1)
Patrick Forget
1
Zakładasz, że będziesz mieć wiele plików w pamięci podręcznej, które były w pamięci podręcznej dłużej niż TTL. c33s ma ważny punkt. Jeśli wszystko było ostatnio dostępne (powiedzmy, że masz 70% pamięci podręcznej, do której dostęp jest uzyskiwany przez cały czas, tak jak chcesz, i masz duży skok, w którym wiele dodatkowych rzadkich plików jest dodawanych naraz), wystąpią błędy rzucony przez TTL sekund. Pamięć podręczna jest pełna i powiedziałeś firmie APC, że nie powinno usuwać tych wpisów, więc narzeka. Jeśli masz czas TTL przez 5 godzin, kończysz z 5-godzinnymi błędami czekającymi na wygaśnięcie tych rzadkich plików.
Matthew Kolb
@MatthewKolb: Nie należy zezwalać na buforowanie większej liczby plików, niż może pomieścić APC w swojej pamięci. Użyj filtrów, aby zapobiec umieszczaniu w pamięci podręcznej plików, do których nie ma dostępu często.
bokan
36

rozwiązanie dla mnie:

  • apc.ttl = 0
  • apc.shm_size = cokolwiek chcesz

początek edycji

ostrzeżenie!

@bokan wskazał mi, że powinienem dodać tutaj ostrzeżenie.

jeśli masz wartość TTL równą 0, oznacza to, że każdy element w pamięci podręcznej można natychmiast wyczyścić. więc jeśli masz mały rozmiar pamięci podręcznej, taki jak 2 MB i wartość ttl równą 0, spowoduje to, że apc będzie bezużyteczne, ponieważ dane w pamięci podręcznej są zawsze nadpisywane.

obniżenie ttl oznacza tylko, że cache nie może się zapełnić, a jedynie przedmiotami, których nie można wymienić.

więc musisz wybrać dobrą równowagę między ttl a rozmiarem pamięci podręcznej.

w moim przypadku miałem pamięć podręczną o wielkości 1 GB, więc to było dla mnie więcej niż wystarczające.

koniec edycji

miał ten sam problem na centos 5 z php 5.2.17 i zauważyłem, że jeśli rozmiar pamięci podręcznej jest mały, a parametr ttl jest „wysoki” (np. 7200), podczas gdy jest dużo plików php do buforowania, pamięć podręczna zapełnia się dość szybko a apc nie znajduje niczego, co może usunąć, ponieważ wszystkie pliki w pamięci podręcznej nadal mieszczą się w ttl.

zwiększenie rozmiaru pamięci jest tylko rozwiązaniem częściowym, nadal występuje ten błąd, jeśli pamięć podręczna się zapełnia, a wszystkie pliki znajdują się w ttl.

więc moim rozwiązaniem było ustawienie ttl na 0, więc apc wypełnia pamięć podręczną i zawsze istnieje możliwość, aby apc wyczyścił trochę pamięci dla nowych danych.

mam nadzieję, że to pomoże

edytuj: zobacz także: http://pecl.php.net/bugs/bug.php?id=16966

pobierz http://pecl.php.net/get/APC wypakuj i uruchom apc.php, tam masz ładny diagram, jak wygląda użycie pamięci podręcznej

c33s
źródło
2
Dziękuję, to pomogło. Otrzymywałem około tuzina błędów „Nie można przydzielić pamięci” na sekundę. Podwoiłem rozmiar pamięci podręcznej (od 32 do 64 MB) i zmniejszyłem wartość ttl do 0. To całkowicie usunęło te błędy.
niesamowite,
1
To była poprawka na naszych serwerach.
Justin
1
Wydawało się, że to rozwiązało również problem dla mnie.
anisoptera
1
Używanie ZWAMP i wydaje się, że to również załatwiło sprawę. Dzięki.
WernerCD,
10
To nie jest rozwiązanie! Błąd znika, ale APC będzie prawie wyłączony. Opróżnia całą pamięć podręczną za każdym razem, gdy pamięć jest pełna. Przeczytaj tylko instrukcję, którą dał nam Brideau. php.net/manual/en/apc.configuration.php#ini.apc.ttl.
bokan
7

Uruchomienie skryptu apc.php jest kluczem do zrozumienia problemu, IMO. Pomogło nam to odpowiednio określić rozmiar naszej pamięci podręcznej i na razie wydaje się, że rozwiązało problem.

Brice D
źródło
1
jak powiedział c33s: pobierz pecl.php.net/get/APC, wypakuj i uruchom apc.php, masz ładny diagram, jak wygląda użycie pamięci podręcznej
bokan
4

Dla początkujących, takich jak ja, te zasoby pomogły:

Znalezienie pliku apc.ini w celu wprowadzenia zmian zalecanych przez c33s powyżej i ustawienie zalecanych ilości: http://www.untwistedvortex.com/optimizing-tuning-apc-alternate-php-cache/

Zrozumienie, czym jest apc.ttl: http://www.php.net/manual/en/apc.configuration.php#ini.apc.ttl

Zrozumienie, czym jest apc.shm_size: http://www.php.net/manual/en/apc.configuration.php#ini.apc.shm-size

Brideau
źródło
Dzięki, wskazałeś właściwe rozwiązanie. Obniżenie TTL jest jak wyłączenie APC.
bokan
4

Jak wspomniał Bokan, możesz zwiększyć pamięć, jeśli jest dostępna, i ma rację, jak bezproduktywne jest ustawienie TTL na 0.

UWAGA: W ten sposób naprawiłem ten błąd dla mojego konkretnego problemu. Jest to ogólny problem, który może być spowodowany przez wiele rzeczy, więc postępuj zgodnie z poniższymi instrukcjami, jeśli pojawi się błąd i uważasz, że jest to spowodowane ładowaniem zduplikowanych plików PHP do APC.

Problem, który miałem, dotyczył wydania nowej wersji mojej aplikacji PHP. To znaczy zastąpiłem wszystkie moje pliki .php nowymi. APC załadowałby obie wersje do pamięci podręcznej.

Ponieważ nie miałem wystarczającej ilości pamięci na dwie wersje plików php, zabrakło pamięci APC.

Dostępna jest opcja o nazwie apc.stat, która nakazuje firmie APC sprawdzenie, czy dany plik się zmienił, a jeśli tak, zastąpienie go, jest to zazwyczaj w porządku w przypadku programowania, ponieważ stale wprowadzasz zmiany, jednak w produkcji jest zwykle wyłączana, tak jak w moim etui - http://www.php.net/manual/en/apc.configuration.php#ini.apc.stat

Włączenie apc.stat rozwiązałoby ten problem, jeśli nie przeszkadza ci osiągnięcie wydajności.

Rozwiązaniem, które wymyśliłem dla mojego problemu, jest sprawdzenie, czy wersja projektu uległa zmianie, a jeśli tak, opróżnij pamięć podręczną i ponownie załaduj stronę.

define('PROJECT_VERSION', '0.28'); 

if(apc_exists('MY_APP_VERSION') ){

    if(apc_fetch('MY_APP_VERSION') != PROJECT_VERSION){
        apc_clear_cache();
        apc_store ('MY_APP_VERSION', PROJECT_VERSION);
        header('Location: ' . 'http'.(empty($_SERVER['HTTPS'])?'':'s').'://'.$_SERVER['SERVER_NAME'].$_SERVER['REQUEST_URI']);
        exit;  
    }

}else{
    apc_store ('MY_APP_VERSION', PROJECT_VERSION);
}
Jase Whatson
źródło
2

To zadziałało dla naszych ludzi (prowadzenie wielu witryn Wordpress na tym samym serwerze).

Zmieniono ustawienia pamięci w pliku /etc/php.d/apc.ini. Był ustawiony na 64 MB, więc podwoiliśmy go do 128 MB.

apc.shm_size = 128M

Peter Drinnan
źródło
1

Przyglądając się internetom, można dostrzec różne przyczyny. W moim przypadku pozostawiając wszystko domyślne z wyjątkiem ...

apc.shm_size = 64M

... usunąłem niezliczone ostrzeżenia, które otrzymywałem wcześniej.

Lew
źródło
1

Otrzymałem błąd „Nie można przydzielić pamięci dla puli” po przeniesieniu instalacji OpenCart na inny serwer. Próbowałem także podnieść memory_limit.

Błąd zatrzymał się po tym, jak zmieniłem uprawnienia do pliku w komunikacie o błędzie, aby użytkownik, z którym działa apache, miał dostęp do zapisu (apache, www-data itp.). Zamiast bezpośrednio modyfikować / etc / group (lub zmieniać pliki do 0777), użyłem usermod:

usermod -a -G vhost-user-group apache-user

Następnie musiałem ponownie uruchomić Apache, aby zmiana odniosła skutek:

apachectl restart

Lub

sudo /etc/init.d/httpd restart

Lub cokolwiek twój system używa do ponownego uruchomienia Apache.

Jeśli witryna jest na hostingu współdzielonym, może musisz zmienić uprawnienia do plików za pomocą programu FTP lub skontaktować się z dostawcą hostingu?

Brent Self
źródło
1

Aby rozwiązać ten problem, ustaw wartość apc.shm_size jako liczbę całkowitą Zlokalizuj plik apc.ini (w lokalizacji pliku apc.ini w moim systemie /etc/php5/conf.d/apc.ini) i ustaw: apc.shm_size = 1000

Biały7
źródło
1

w moim systemie musiałem wstawić apc.shm_size = 64M do /usr/local/etc/php.ini (FreeBSD 9.1), a następnie kiedy spojrzałem na apc.php (skopiowałem z / usr / local / share / doc / APC /apc.php do / usr / local / www / apache24 / data) stwierdziłem, że rozmiar pamięci podręcznej wzrósł z domyślnego 32 MB do 64 MB i nie otrzymywałem już dużej liczby pełnej pamięci podręcznej

referencje: http://au1.php.net/manual/en/apc.configuration.php czytaj także komentarze Bokana, były bardzo pomocne

Andrzej
źródło
0

Monitoruj rozmiar plików buforowanych (możesz użyć apc.php z pakietu apc pecl) i zwiększ apc.shm_size zgodnie ze swoimi potrzebami.

To rozwiązuje problem.

lazcorp
źródło