Kontakt z pomocą

Odpowiadamy e-mailem, zwykle w ciągu dwóch dni.

Google reCAPTCHA sprawdza to zgłoszenie pod kątem nadużyć; dane trafiają do Google. Skrypt ładuje się dopiero po otwarciu formularza.

← Wszystkie wpisy

Każde wywołanie ładuje całe lib/

Wiersz 46 jedynego pliku wejściowego tej usługi:

foreach (glob(__DIR__ . '/lib/*.php') as $f) { require_once $f; }

To 65 plików i 1,5 megabajta, ładowane przy każdym wywołaniu. Obrazek licznika, strona statystyk, błąd 404 — wszystko tak samo. Wczoraj zdarzyło się to 20 734 razy.

26 rodzin wzorów — 715 KB, używana jest jedna flagi 189 KB · wykresy 158 KB · cała reszta 470 KB na zimno, bez cache kodu: 132 ms kod z dysku: 18,2 ms kod we wspólnej pamięci: 0,33 ms — glob i 65 stat 65 plików, 1,5 MB, 56 klas, przy każdym wywołaniu

Liczba, o którą chodzi, to ta mała

Wczytanie wszystkiego od zera, z wyłączonym cache kodu, trwa około 132 milisekund. To liczba, która zrobiłaby z tego skandal, i to nie jest liczba, którą płaci serwer.

Gdy kod jest już skompilowany i leży we wspólnej pamięci, zostaje wypisanie katalogu i jedno stat() na plik, bo sprawdzanie znaczników czasu jest włączone: 0,33 milisekundy. Przy wczorajszym ruchu to niecałe siedem sekund pracy przez cały dzień.

Pomiędzy leży trzeci pomiar, 18,2 milisekundy, z cache kodu czytającym z dysku zamiast z pamięci. To górne ograniczenie, a nie prawdziwa wartość — to, co się dzieje, gdy cache jest, ale wolniejszy niż ten właściwy. Podaję go, bo to jedyna ciepła wartość, którą da się zmierzyć z wiersza poleceń, a twierdzenie czegoś innego byłoby wygodnym błędem.

Czyli: to kosztuje prawie nic, i kosztuje prawie nic wyłącznie dzięki czemuś innemu. Wyłącz cache kodu, a ten sam wiersz kosztuje czterysta razy więcej. To prawdziwa zależność i lepiej o niej wiedzieć, niż odkryć ją przy aktualizacji.

Co naprawdę siedzi w tych 1,5 megabajta

Czterdzieści siedem procent — 715 kilobajtów w 26 plikach — to rodziny wzorów liczników. Narysowanie obrazka licznika potrzebuje dokładnie jednej z nich. Pozostałe 25 są ładowane, zgłaszane i nigdy nietykane.

Dalej: 189 kilobajtów danych flag, potrzebnych na stronie krajów; 158 kilobajtów biblioteki wykresów, potrzebnej, gdy coś rysuje wykres. Żadne z nich nie bierze udziału w rysowaniu obrazka licznika, a to jest wywołanie, na które ta usługa odpowiada częściej niż na jakiekolwiek inne.

Widać to bardziej w pamięci niż w czasie. Szczyt na wywołanie rośnie o jakieś cztery megabajty, i w odróżnieniu od kodu — który dzielą wszystkie procesy — ta część jest płacona na każde wywołanie, równolegle, przez każdego pracownika naraz.

Ktoś już to zauważył

Glob brzmi lib/*.php. Nie schodzi w głąb, a tuż pod nim leżą dwa katalogi: lib/live/ z 229 kilobajtami i lib/recht/ z 182 kilobajtami. Czterysta kilobajtów, które kiedyś były na ścieżce ładowania, a teraz nie są.

Przeniesiono je, bo są duże i rzadko potrzebne: sekcje statystyk i teksty prawne. Bycie o jeden katalog głębiej to cały mechanizm. Nie ma ustawienia, nie ma doładowywacza, nie ma mapy autoload — plik jest w globie albo go nie ma.

To prawdziwa naprawa i warto to powiedzieć, bo oczywistym następnym krokiem byłby autoloader, a autoloader byłby tu dużą zmianą dla problemu, który mkdir rozwiązał już dwa razy.

Dlaczego zostaje

Pojedynczy glob to najprostsza rzecz, jaka w ogóle może zadziałać, a z pomiaru wynika, że działa: jedna trzecia milisekundy, na Raspberry Pi, na ścieżce, która musi być szybka. Zastąpienie go pojedynczymi wywołaniami znaczy, że każdy nowy plik potrzebuje gdzieś wiersza, a zapomniany wiersz daje awarię na produkcji zamiast trochę większego ładowania.

Brakuje spisania tego, co w ogóle uczyniło to znośnym: gdy plik w lib/ robi się duży, przenosi się do podkatalogu i jest wczytywany tam, gdzie jest potrzebny. Właśnie tej reguły trzymały się te dwa katalogi, a nigdzie nie była zapisana aż do dziś.

Wersja ogólna jest nudniejsza niż pomiar. „Wszystko ładuje wszystko" to zwykle zły kształt i warto wiedzieć, czy cokolwiek to kosztuje, zanim się to przebuduje. Tutaj kosztuje 0,33 milisekundy i cztery megabajty, a te cztery megabajty są tą częścią, którą warto obserwować, bo rosną z równoczesnością, a milisekundy nie.

Reklama