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.