PHP profiling z Xdebug 3 — cachegrind i KCachegrind
Opublikowano: 10 kwietnia 2026 · Kategoria: Wydajność
WordPress ładuje się powoli, ale nie wiesz która funkcja to powoduje. Xdebug 3 pozwala nagrać każde wywołanie funkcji PHP z czasem wykonania — plik cachegrind otwierasz w KCachegrind i widzisz dokładnie co zajmuje 80% czasu. Ten przewodnik pokazuje instalację, konfigurację trybu profilowania i interpretację wyników. Na końcu porównanie z Blackfire.io.
Instalacja Xdebug 3
# Ubuntu / Debian — przez pecl lub apt sudo apt install -y php-xdebug # Lub przez pecl (najnowsza wersja) sudo pecl install xdebug # Sprawdź zainstalowaną wersję php -v # PHP 8.2.x (cli) with Xdebug v3.3.x # Znajdź plik konfiguracyjny PHP php --ini | grep "Loaded Configuration" # Zazwyczaj: /etc/php/8.2/cli/php.ini lub /etc/php/8.2/fpm/php.ini # Znajdź katalog conf.d php --ini | grep "additional .ini" # Zazwyczaj: /etc/php/8.2/fpm/conf.d/ # Sprawdź czy Xdebug jest załadowany php -m | grep xdebug
Konfiguracja xdebug.ini — tryby pracy
Xdebug 3 wprowadził fundamentalną zmianę: jeden parametr xdebug.mode kontroluje wszystkie
funkcje. Nie włączaj wielu trybów jednocześnie bez potrzeby — każdy dodaje narzut. Poniżej konfiguracje
dla różnych scenariuszy:
# /etc/php/8.2/fpm/conf.d/20-xdebug.ini [xdebug] zend_extension = xdebug.so # ============================================================ # TRYB: profiling — nagrywanie wywołań funkcji do cachegrind # ============================================================ xdebug.mode = profiling xdebug.output_dir = /tmp/xdebug # katalog na pliki cachegrind xdebug.profiler_output_name = cachegrind.out.%p.%r # %p=PID, %r=random xdebug.start_with_request = trigger # tylko gdy XDEBUG_PROFILE=1 w URL/cookie # ============================================================ # TRYB: debug — step debugger (VS Code, PhpStorm) # ============================================================ ; xdebug.mode = debug ; xdebug.client_host = 127.0.0.1 ; xdebug.client_port = 9003 ; xdebug.start_with_request = yes # ============================================================ # TRYB: coverage — code coverage dla PHPUnit # ============================================================ ; xdebug.mode = coverage # ============================================================ # TRYB: develop — ulepszone var_dump, error reporting # ============================================================ ; xdebug.mode = develop # Kombinacja (np. debug + develop): ; xdebug.mode = debug,develop
# Utwórz katalog na pliki profilowania i nadaj uprawnienia
sudo mkdir -p /tmp/xdebug
sudo chown www-data:www-data /tmp/xdebug
# Przeładuj PHP-FPM po zmianie konfiguracji
sudo systemctl reload php8.2-fpm
# Weryfikacja: sprawdź czy tryb profiling jest aktywny
php -r "echo xdebug_info('mode');" 2>/dev/null || php -r "xdebug_info();" | grep mode Uruchamianie profiling — trigger mode
# Z parametrem URL (GET) curl "https://mojadomena.pl/?XDEBUG_PROFILE=1" -o /dev/null # Z nagłówkiem HTTP (nie modyfikuje URL aplikacji) curl "https://mojadomena.pl/" \ -H "Cookie: XDEBUG_PROFILE=PHPSTORM" -o /dev/null # Przez Xdebug Helper (rozszerzenie Chrome/Firefox) # Kliknij ikonę → wybierz Profile → odśwież stronę # Sprawdź wygenerowane pliki cachegrind ls -la /tmp/xdebug/ # -rw-r--r-- 1 www-data www-data 1.8M cachegrind.out.12345.a1b2c3 # Dla CLI (np. profilowanie skryptu PHP) XDEBUG_MODE=profiling XDEBUG_OUTPUT_DIR=/tmp/xdebug \ php moj-skrypt.php # Profilowanie konkretnej strony WordPress XDEBUG_MODE=profiling php /var/www/wordpress/wp-cron.php
Analiza w KCachegrind / QCachegrind
KCachegrind (Linux) i QCachegrind (Windows/macOS) to graficzne narzędzia do analizy plików
cachegrind. Otwórz plik z /tmp/xdebug/ i skup się na trzech widokach:
# Instalacja KCachegrind (Linux) sudo apt install kcachegrind # Instalacja QCachegrind (Windows — dostępny jako portable binary) # Pobierz z: https://github.com/KDE/kcachegrind # Otwórz plik cachegrind kcachegrind /tmp/xdebug/cachegrind.out.12345.a1b2c3 # Kluczowe widoki i kolumny: # Flat Profile — sortuj po "Self" (czas w tej funkcji, bez wywołań) # → Szukaj funkcji z Self > 5% — to kandydaci do optymalizacji # # Call Graph — wizualizacja grafu wywołań # → Grube strzałki = gorące ścieżki wywołań # # Callee Map (treemap) — proporcjonalna mapa funkcji według czasu # → Duże prostokąty = funkcje z największym kosztem # Alternatywa online: wgrep plik cachegrind na # https://www.speedscope.app (format cachegrind obsługiwany)
WordPress — typowe wąskie gardła
# Profiling WordPress — szukaj tych problemów w KCachegrind:
# 1. Zbyt wiele zapytań SQL
# Funkcja: wpdb::query — duże Self Time, setki wywołań
# Fix: cache WP_Query, używaj transients, ogranicz pętle WP_Query
# 2. Nieoptymalne WP_Query / get_posts
# Fix: dodaj 'no_found_rows' => true (wyłącza SQL_CALC_FOUND_ROWS)
# 'update_post_meta_cache' => false (gdy nie potrzebujesz meta)
# 'update_post_term_cache' => false (gdy nie potrzebujesz taksonomii)
# Przykład optymalnego WP_Query:
# $args = array(
# 'posts_per_page' => 10,
# 'no_found_rows' => true,
# 'update_post_meta_cache' => false,
# 'update_post_term_cache' => false,
# );
# 3. Niebuforowane opcje WordPress (wp_options z autoload=yes)
# Sprawdź przez: SELECT option_name, LENGTH(option_value)
# FROM wp_options WHERE autoload='yes' ORDER BY LENGTH(option_value) DESC;
# Fix: usuń autoload dla dużych opcji pluginów
# 4. Zewnętrzne HTTP w hookach
# Funkcja: WP_HTTP::request lub curl_exec — duże czasy oczekiwania
# Fix: cache odpowiedzi API przez set_transient()
# 5. Powolne pluginy w wp_head / wp_footer
# Sprawdź hook: do_action('wp_head') — czas Self vs Inclusive
# Fix: usuń zbędne pluginy, lazy-load przez wp_enqueue_scripts Blackfire.io — alternatywa do profilowania produkcji
| Cecha | Xdebug 3 | Blackfire.io |
|---|---|---|
| Cena | Darmowy (open-source) | Darmowy plan (1 środowisko) + płatne |
| Narzut wydajności | 2-5x wolniej (profilowanie) | <5% (zoptymalizowany do produkcji) |
| UI / wizualizacja | KCachegrind (lokalne) lub speedscope | Wbudowany UI w przeglądarce, timeline |
| CI/CD integracja | Manualna (phpunit --coverage) | Natywna (GitHub Actions, GitLab CI) |
| Alerty anomalii | Brak | Automatyczne alerty (regresje wydajności) |
| Wsparcie dla produkcji | Trigger mode (ograniczone) | Tak (stały monitoring z minimalnym narzutem) |
| Najlepszy dla | Lokalne dev, step debugger, code coverage | Produkcja, CI/CD, porównywanie wersji |
# Instalacja Blackfire agent i PHP extension curl -sS https://packages.blackfire.io/gpg.key | sudo gpg --dearmor \ -o /usr/share/keyrings/blackfire.gpg echo "deb [signed-by=/usr/share/keyrings/blackfire.gpg] http://packages.blackfire.io/debian any main" \ | sudo tee /etc/apt/sources.list.d/blackfire.list sudo apt update && sudo apt install -y blackfire blackfire-php # Skonfiguruj agenta (klucze z blackfire.io/my/settings/credentials) sudo blackfire agent:config # Przeładuj PHP-FPM sudo systemctl reload php8.2-fpm # Profiluj przez CLI blackfire curl https://mojadomena.pl/ # Profiluj przez przeglądarkę # Zainstaluj Blackfire Companion (Chrome/Firefox) # Kliknij ikonę → Profile → otwórz wyniki na blackfire.io