Refaktoryzacja Wordpress w celu poprawy wydajności pamięci [zamknięte]

63

Przyjrzałem się uważnie zużyciu pamięci Wordpress. Na mojej stronie wydaje się, że dla każdej trafionej strony przydzielane jest 20 MB pamięci RAM, aby przygotować wygodne środowisko dla wszystkich wtyczek do działania. Zrobiłem to w ten sposób:

Nie ma jednego miejsca do optymalizacji, ani jednego złego faceta, który zjada większość pamięci. Zużycie jest rozłożone na wiele wielu modułów php.

Jak sprawić, by Wordpress zainicjował środowisko w pamięci tylko raz, a następnie używał go wiele razy dla każdego trafienia? Nie chcę, aby powolny PHP zjadał 20 MB przy każdym kliknięciu użytkownika - nawet na serwerze z dużą ilością pamięci, wykonanie całej pracy zajmuje kilka sekund. Zasadniczo potrzebujesz fragmentów pamięci tylko do odczytu, które można ponownie wykorzystać.

Także ... dlaczego 20 MB? Czy ktoś może wgląd w to?

Edycja: Oto dane wyjściowe WinCacheGrind na Wordpress uruchomionym na mojej maszynie programistycznej (znacznie szybsze niż hosting współdzielony). Jak widać, zajmuje więcej czasu, niż samo wygenerowanie kodu HTML strony głównej. Zwolnij to, udostępniając hosting, a masz przepis na kłopoty. Wybrałem metodę, która zajmuje większość czasu. Jak poszedłbyś na optymalizację tego?

Edycja: Oto statystyki zapytań z tego fantastycznego narzędzia do profilowania funkcji.php .

Obciążenie: 12 zapytań - 532 ms - 19,1 MB - 43 trafień w pamięci podręcznej / 53
Zapytanie: 15 zapytań - 563 ms - 19,0 MB - 72 trafień w pamięci podręcznej / 86
Wyświetlanie: 21 zapytań - 705 ms - 19,2 MB - 234 trafień w pamięci podręcznej / 257

Edycja: Czy chcesz zobaczyć coś, co cię przerazi? Wstaw te linie na końcu index.php:


echo "<pre>\n";
print_r(get_defined_vars());
echo "</pre>\n";

Próbowałem policzyć, ile razy ciało aktualnego postu jest przechowywane w pamięci. Naliczyłem 20 wystąpień. Potem zdałem sobie sprawę, że PHP ma liczenie referencji, więc liczba kopii zredukowana do zaledwie trzech: dwie wydają się być w WP_Query, jedna w pamięci podręcznej obiektów. Badam dalej.

Dlatego myślę, że WordPress potrzebuje refaktoryzacji w celu rozwiązania problemów z pamięcią. Nie można już obwiniać o zużycie pamięci samej złożoności tego, co robi. Po prostu robi to źle .

Edycja: Po dniu prób zrobienia tego, oto moje ustalenia:

1) 88% całej pamięci pochodzi z wywołań typu wymagającego lub dołączającego lub obejmującego:

2) Plik php zawiera się głównie podczas pierwszej części obsługi żądania (co nie jest zaskakujące), czyli tam, gdzie pochłania się całą pamięć:

3) Interesujące jest wykreślenie wszystkich funkcji, które są wykonywane podczas wysyłania żądania. Łącznie jest ponad 12000 połączeń. Drgałem je, aby było bardziej widoczne (oś Pozioma to zasadniczo głębokość stosu):

4) Jedynym sposobem, jaki mogę wymyślić, jest zminimalizowanie liczby zawartych plików .php. Jeśli podzielę funkcje na pliki, z których pochodzą, możesz zobaczyć, że wiele plików zostało trafionych raz lub dwa razy. Potrzebujemy sposobu, aby pominąć te, które nie są potrzebne. Na przykład moja wtyczka do zdalnej kopii zapasowej bazy danych jest ładowana i rejestrowana, tak aby nigdy nie była używana. Oto powyższy wykres podzielony według nazwy pliku:

Oferuję nagrodę wartą całej mojej reputacji :) za refaktoryzacje, które doprowadziłyby do zmniejszenia śladu pamięci moich blogów o 30% lub więcej.

Edycja: Zainstalowałem WP 3.1, oto porównanie ze starą wersją.

Niebieski to WP 3.1, czerwony to 3.0.4. Nowa WP jest szybsza, ale zużywa także więcej pamięci.

Oto lista plików dołączanych.

Pozwoliło mi to uświadomić sobie, ile pamięci zużywa „pakiet All In One SEO” - jedną z możliwości byłoby użycie tylko ułamka funkcjonalności wtyczki, aby uzyskać to, czego chcę. Poza tym moje własne wtyczki wydają się całkiem złe.

Chciałbym spróbować załadowania warunkowego np. Comment.php (nie zezwalam na komentarze na moim blogu) i kilku innych. Usunąłem cały przestarzały kod. Zmniejszyłem plik kses.php, aby ładował tylko jego globalne tabele na żądanie. Uprościłem l10n (nie dokonuję lokalizacji), dzięki czemu jego funkcje od razu zwracają ciągi, bez wyszukiwania. Nadal jestem daleki od 30% oceny, którą sam ustaliłem.

Edycja: Pobrałem i włączyłem APC z ustawieniami domyślnymi (32 MB pamięci podręcznej opcode). Oto porównanie:

Widać, że ładowanie kodu znacznie przyspieszyło, a także zajmuje mniej miejsca w pamięci (prawdopodobnie dlatego, że mamy do czynienia tylko z kodami, a nie oryginalnym źródłem). Zużycie pamięci jest jednak nadal dość wysokie.

Roman Zenka
źródło
Czy mógłbyś gdzieś przesłać sam plik cachegrind? Pamiętaj tylko, że nie pamiętam, czy zawiera w sobie coś, co warte jest zachowania prywatności, jeśli tak, to nie.
Rarst
@Rarst Powinno być w porządku. foxloft.com/files/mbala/cachegrind.out
Roman Zenka
1
hm, zgadzam się z twoją konkluzją - nic tak naprawdę nie wyskakuje z prośbą o naprawienie. Zrzuciłem świeży profil na mój lokalny stos testowy (3.1, MS, Twenty Ten, dane Theme Unit Test) i dostałem 1,5s (większość różnic wydaje się wynikać z niestandardowego menu - wszystko jest powolne). Chyba nic do naprawienia = buforowanie badań.
Rarst
@Rarst Bardzo dziękuję za pomoc. Myślę, że są rzeczy do naprawienia, ale wymagałoby to zmiany architektury Wordpress na zupełnie inną filozofię, a to za dużo pracy.
Roman Zenka

Odpowiedzi:

25

Nie warte kłopotów. WordPress nie zjada dużo pamięci tylko dlatego. Zjada dużo pamięci, ponieważ działa pod wieloma funkcjami.

O wiele łatwiej i wydajniej jest buforować wyniki (generowane strony) za pomocą statycznej wtyczki pamięci podręcznej i obsługiwać ją. W ten sposób większość odwiedzających nawet nie trafi w WP.

Rarst
źródło
2
Korzystam już z pamięci podręcznej, ale nadal mam kilka stron, które mają naprawdę dynamiczny charakter (np. Koszyk na zakupy). A kiedy gwiazdy nie są prawidłowo ustawione, użytkownik może poczekać 20 sekund - to znaczy, przyznane, na GoDaddy, ale nawet jeśli nie, myślę, że będzie to co najmniej ~ 3 sekundy. Po prostu nie mogę zapewnić tego rodzaju naprawdę zgryźliwych doświadczeń, do których ludzie są przyzwyczajeni z Google.
Roman Zenka
8
@Roman Zenka, jeśli masz określone potrzeby w zakresie wydajności, lepiej jest szukać konkretnych rozwiązań, niż mieć nadzieję, że sam WordPress w magiczny sposób stanie się super szybki i nie będzie obciążał zasobów. Pierwszą rzeczą, na którą zasugerowałem, jest pamięć podręczna opcode i buforowanie statyczne fragmentów ... Ale zanim to nastąpi, musisz sprawdzić, co się dzieje, i określić nie tylko, dokąd zmierza pamięć, ale także gdzie spędzić czas. WordPress to środowisko, a nie samo wąskie gardło. Wąskie gardło polega na tym, co robisz.
Rarst
@Rarst Rzeczywiście przeprowadziłem testy porównawcze wykorzystania procesora i nie mogę wskazać żadnego konkretnego miejsca, które powoduje problemy. Podobnie jak pamięć - wydaje się, że jest rozrzucona po całym miejscu. Jednak moje testy porównawcze mogą nie zostać wykonane w optymalny sposób - używam profilera XDebug i Cachegrind - na przykład dość trudno jest rozdzielić opóźnienia z powodu wywołań bazy danych. Byłbym wdzięczny za wskazówki dotyczące lepszych technik profilowania.
Roman Zenka
Dodano zrzut ekranu @Rarst Profiling.
Roman Zenka
4
Mogą to być również powolne serwery GoDaddy. Są znani z tego, że nie mają najlepszego sprzętu i „ wolą płacić za reklamy telewizyjne niż ulepszać swoje serwery
Zack
23

I dlatego uważam, że WordPress naprawdę potrzebuje przepisania. Nie można już obwiniać o zużycie pamięci samej złożoności tego, co robi. Po prostu robi to źle.

Co za naiwny wniosek. Czytaj Co należy nigdy nie robić, część I .

Dzięki za wykresy wykorzystania pamięci.

Znacznie późniejsza edycja: Autommatic wydało bibliotekę o nazwie prefork, która wydaje się robić to, o co prosisz: ładowanie kodu WordPress do pamięci RAM tylko raz.

scribu
źródło
To prawda, że ​​jest naiwny. Może powinienem był powiedzieć „refaktor” zamiast „przepisać”, a wtedy brzmi to znacznie lepiej. Opublikowana aktualizacja.
Roman Zenka
2
Ok, cóż, jeśli masz konkretne sugestie (szczególnie łatki), możesz je opublikować na trac: core.trac.wordpress.org
scribu
Pracuję nad tym teraz. Próbuję wykreślić mapę obiektów w pamięci, aby zobaczyć, ile z nich zostanie wykorzystane. Czy istnieje narzędzie, które wykonałoby zrzut pamięci i wykreśliło go?
Roman Zenka
5
@scribu - +1 za link do posta Joela!
MikeSchinkel
1
Ok, pamiętaj tylko, że WP_Object_Cache można zastąpić implementacją memcached itp.
scribu
17

Począwszy od WordPress 3.2, PHP 5.2 będzie minimalnym wymaganiem. Myślę, że dzięki naszym paskom fragmenty rdzenia można zacząć restrukturyzować i używać klas z automatycznym ładowaniem. Pozwoliłoby to uniknąć ładowania niektórych fragmentów kodu, o ile nie były one faktycznie potrzebne. Na przykład, jeśli w widoku strony nie było osadzania ani galerii, moglibyśmy uniknąć załadowania dużej części kodu multimediów.

Jednak nawet jeśli zdecydują się pójść tą drogą, oczekiwałbym, że będzie to powolna ewolucja (podobnie jak wiele innych ukrytych zmian, które miały miejsce). Wymagałoby to przetasowania wokół lokalizacji wielu plików i kodu, co może spowodować uszkodzenie kompatybilności wstecznej dla niektórych wtyczek.

Część problemu (jeśli można to tak naprawdę nazwać) polega na tym, że bez tego rodzaju ładowania warunkowego, podstawowa struktura nie może z góry wiedzieć, jakiej funkcjonalności będzie potrzebować, czy nie, aby wygenerować widok zawartości. Wiele funkcji musi zostać załadowanych na wypadek , gdyby były potrzebne.

Dougal Campbell
źródło
@Dougal Campbell Rozpocząłem nagrodę za to pytanie, aby sprawdzić, czy możemy zhakować przynajmniej jeden przypadek WordPressa wystarczająco źle, aby uzyskać względnie bezbolesne zwiększenie zużycia pamięci o co najmniej 30%. Może zainspirować część przyszłego rozwoju.
Roman Zenka
Ładowanie warunkowe, potencjalnie zmniejszając zużycie pamięci, zmniejsza szybkość, gdy w grę wchodzi buforowanie kodów operacyjnych . Stawiamy na prędkość.
scribu
Więcej przemyśleń na temat automatycznego ładowania: stackoverflow.com/questions/4788452/...
scribu
@scribu Kiedy mówisz „ładowanie warunkowe”, czy mówisz o automatycznym ładowaniu, czy faktycznie ładowaniu kodu na podstawie warunku? Jak bardzo boli prędkość?
Roman Zenka
1
Dziękuję Ci! Jak powiedziałem, nie wiem, czy rdzeń WP kiedykolwiek wybierze tę trasę (wymagane refaktoryzowanie może być zbyt ekstremalne). Byłem jednak pod wrażeniem wysiłku włożonego w analizę tego i twoich wykresów. Tak trzymaj!
Dougal Campbell,
16

Jak sprawić, by Wordpress zainicjował środowisko w pamięci tylko raz, a następnie używał go wiele razy dla każdego trafienia?

Nazywa się to buforowaniem opcode.

http://en.wikipedia.org/wiki/PHP_accelerator

Otto
źródło
1
Dam APC szansę i zobaczę, co się stanie. Kiedy pierwotnie zadałem to pytanie, miałem na myśli więcej niż tylko buforowanie opcode - miałem na myśli ponowne wykorzystanie całego środowiska, które buduje WordPress - kod + dane. Memcached pomoże ci szybciej uzyskać dane, ale nadal będziesz klonował dane w pamięci serwera. Teraz wydaje się, że buforowanie opcode potencjalnie zająłoby ~ 90% całego zużycia pamięci.
Roman Zenka
Jeśli masz zasoby na niektóre eksperymenty, możesz także spróbować skonfigurować środowisko FastCGI. Byłbym bardzo zainteresowany porównaniami między mod_php a działaniem pod FastCGI.
Dougal Campbell
5

prawdopodobnie nie uda ci się tak bardzo ograniczyć użycia pamięci RAM. Ale jeśli używasz mod_php, możesz mod_fcgidzamiast tego przejść na .

podczas gdy mod_php jest nieco wolniejszy, ładuje php, nawet gdy nie jest to konieczne, takie jak wyświetlanie obrazów, plików statycznych, a nawet buforowanie. Jeśli masz dużo próśb, to dużo pamięci RAM.

użycie fcgid znacznie to zmniejszy.

także użycie statycznej pamięci podręcznej (takiej jak w3total cache) pozwoli w ogóle uniknąć wywoływania php, co jest naprawdę wielką zaletą: mniejsze zużycie pamięci RAM, mniej połączeń db.

Boyska
źródło
4

Ha. Pracuję teraz nad aplikacją internetową, która w pełni zamierzam przeciążać danymi i użytkowaniem wykraczającym poza to, co może obsłużyć moje konto hostingu współdzielonego, więc zdecydowałem - choć byłoby to bardzo łatwe do zbudowania w WP - spróbować pracy z BackPress jako ramy i buduj tylko to, czego potrzebowałem dla moich konkretnych przypadków użycia.

Więc byłem w stanie zredukować moje podstawowe środowisko z setek plików PHP w WP do zaledwie dwudziestu, których tak naprawdę potrzebuję, a jednocześnie nadal jestem w stanie wykorzystać wszystkie db, HTTP, zarządzanie użytkownikami, formatowanie i cron funkcje, które kocham w WordPress.

Problem polega na tym, że to dużo pracy i nigdy nie zaufałbym mojej hackjobowi do niczego poza własnym użytkiem. Jeśli chcesz korzystać z pełnego środowiska WP, weź go takim, jakim jest. Jest tak dobry, jak to jest, ponieważ setki programistów dostosowuje go przez kilka lat. Jak wszyscy tutaj mówili, znajdziesz się znacznie dalej, znajdując lepszy plan hostingu i badając techniki buforowania, niż prawdopodobnie zhakujesz rdzeń.

Złote Jabłka
źródło
1
Zgadzam się, że WP było dostrajane od dłuższego czasu. Ale nie sądzę, żeby była dobrze dostosowana do pracy na cholernym hostingu, ze szczególną mieszanką wtyczek. Jestem ciekawy, jak daleko mogę to przesunąć. Nawet jeśli zmiany nie wprowadzą się do rdzenia, dobrze jest mieć udokumentowany sposób włamania się do rdzenia, jeśli uważasz, że musisz.
Roman Zenka
3

Tak, WordPress najpierw ładuje wszystko, a następnie robi to, o co prosimy. Pamiętam gdzieś, że możemy stworzyć wirtualną pulę w pamięci RAM, w której możemy umieścić pliki. Wpadłem na pomysł, aby umieścić cały WordPress w pamięci (<10 MB), a następnie możemy zaoszczędzić dużo I / O, które same powinny dać przyspieszenie. Ale nigdy nie miałem okazji tego spróbować, a ponadto nie jestem zbyt biegły w dążeniu do czegoś takiego. Ale wygląda na to, że warto spróbować.

Popiół
źródło
Zgadzam się z Rarst na użycie wtyczki statycznej pamięci podręcznej, aby żadne przetwarzanie nie było w ogóle wykonywane. Ale można tego również używać z dobrą dynamiką. :)
Ashfame
Podoba mi się ten pomysł. Nie jestem pewien, ile z tego problemu wynika z opóźnień we / wy, a ile z powodu powolnego żucia danych przez PHP. Czy wiesz jak to powiedzieć?
Roman Zenka
Przepraszam, to tylko pomysł w mojej głowie. Być może nie wpływa to tak bardzo na wydajność, jak może się wydawać, ponieważ dane są zwykle odczytywane z dysku twardego jako bloki, więc wiele innych wymaganych danych mogło już zostać pobranych. Nie jestem zbyt pewny.
Ashfame,
3

kilka podstawowych sugestii:

  1. w3 całkowita pamięć podręczna wtyczki do buforowania ..
  2. zainstaluj i włącz memcache, włącz także z ustawień całkowitej pamięci podręcznej w3 (pamięć podręczna opcodu jest również dobrą opcją, ale nie idzie dobrze z wtyczką całkowitej pamięci podręcznej w3)
  3. zminimalizuj zapytania kierujące bezpośrednie linki w plikach motywów.
  4. Wyłącz wszystkie dodatkowe nieużywane wtyczki i usuń.
  5. optymalizuj bazę danych.

prowadzę dobrze znaną witrynę Wordpress z ogromnym ruchem codziennie .. nie jestem nawet poświęcony, świetnie się dla mnie :)

Ayaz Malik
źródło