var_dump() i microtime() to debugowanie na oko. Blackfire to profesjonalny profiler który pokazuje dokładnie ile czasu i pamięci zajmuje każde wywołanie funkcji w całym stosie – w czasie rzeczywistym, z wizualizacją call graph. Pokazuję jak zainstalować Blackfire w DDEV, jak profilować requesty HTTP i komendy CLI, i jak interpretować wyniki żeby znaleźć prawdziwe wąskie gardła w Magento 2.
Blackfire vs inne narzędzia profilujące
| Narzędzie | Co mierzy | Narzut na wydajność | Produkcja? |
|---|---|---|---|
| microtime() | Czas wybranego fragmentu kodu | Minimalny | Tak |
| Xdebug profiler | Pełny call graph, czas, liczba wywołań | Bardzo duży (5-10x) | Nie |
| Blackfire | Pełny call graph, CPU, RAM, I/O | Mały (2x) | Możliwe (ostrożnie) |
| New Relic APM | Agregacja metryk, slow queries | Minimalny | Tak (do tego służy) |
| Tideways XHProf | Call graph, czas, pamięć | Mały | Możliwe |
Instalacja w DDEV
# Blackfire wymaga konta na blackfire.io (darmowe dla developerów) # Po rejestracji dostaniesz Server ID i Server Token # Dodaj Blackfire do DDEV projektu ddev get ddev/ddev-blackfire # Lub ręcznie - .ddev/docker-compose.blackfire.yaml
# .ddev/docker-compose.blackfire.yaml
version: '3.6'
services:
blackfire:
image: blackfire/blackfire:2
environment:
BLACKFIRE_SERVER_ID: "${BLACKFIRE_SERVER_ID}"
BLACKFIRE_SERVER_TOKEN: "${BLACKFIRE_SERVER_TOKEN}"
BLACKFIRE_CLIENT_ID: "${BLACKFIRE_CLIENT_ID}"
BLACKFIRE_CLIENT_TOKEN: "${BLACKFIRE_CLIENT_TOKEN}"
labels:
com.ddev.site-name: ${DDEV_SITENAME}
web:
environment:
BLACKFIRE_AGENT_SOCKET: "tcp://blackfire:8307"
# Ustaw tokeny w .ddev/.env (nie commituj do repo!) echo "BLACKFIRE_SERVER_ID=twoje-server-id" >> .ddev/.env echo "BLACKFIRE_SERVER_TOKEN=twoj-token" >> .ddev/.env # Zainstaluj probe PHP w kontenerze web ddev ssh pecl install blackfire # Zrestartuj ddev restart
Profilowanie requestu HTTP
# Przez CLI - profiluj konkretny URL
blackfire curl https://magento2-dev.ddev.site/catalog/product/view/id/42
# Z przeglądarki - zainstaluj rozszerzenie Blackfire Companion
# (Chrome/Firefox) i kliknij przycisk Profile
# Profilowanie z parametrami
blackfire curl \
--samples 5 \ # średnia z 5 requestów
https://magento2-dev.ddev.site/
# Profilowanie komendy CLI - bardzo przydatne dla Magento
blackfire run php bin/magento catalog:reindex
blackfire run php bin/magento indexer:reindex catalog_product_price
Interpretacja wyników – call graph
Blackfire pokazuje call graph jako drzewo wywołań. Kluczowe metryki:
- Wall Time – całkowity czas wykonania (z czekaniem na I/O)
- CPU Time – czas procesora (bez I/O wait)
- Memory – szczytowe zużycie pamięci
- I/O Time – czas spędzony na operacjach I/O (baza, pliki)
- HTTP calls – liczba requestów do zewnętrznych serwisów
<?php
// Typowe problemy które Blackfire ujawnia w Magento 2:
// 1. N+1 queries - widać jako setki wywołań mysql_query
// Rozwiązanie: eager loading przez joinField() lub zbiorcze zapytania
// 2. Zbędna serializacja/deserializacja
// Widać jako dużo czasu w json_decode/json_encode w pętlach
// 3. Layout rendering - czas w Magento\Framework\View\Layout::generateXml
// Rozwiązanie: cache layout, lazy loading bloków
// 4. Plugin chains - dużo czasu w Interceptor::__callPlugins
// Rozwiązanie: sprawdź czy plugin naprawdę musi być "around"
// Przykład - instrumentacja własnego kodu dla Blackfire
class ProductImporter
{
public function importBatch(array $products): void
{
// Blackfire SDK - oznacz sekcję kodu jako "transaction"
$probe = \BlackfireProbe::getMainInstance();
$probe->createTransaction('Product Import Batch', count($products) . ' products');
foreach ($products as $product) {
$this->importSingle($product);
}
$probe->stopTransaction();
}
}
Blackfire Builds – automatyczne profilowanie w CI/CD
# .blackfire.yaml - scenariusze testowe i asercje wydajnościowe
scenarios:
Homepage:
- /
Product Page:
- /catalog/product/view/id/42
Category:
- /women/tops-women/jackets-women.html
# Asercje - CI/CD zakończy się błędem jeśli przekroczone
tests:
"Homepage loads fast":
path: /
assertions:
- "main.wall_time < 2s"
- "main.peak_memory < 64mb"
- "metrics.sql.queries.count < 30"
"No slow queries":
path: /
assertions:
- "metrics.sql.queries.wall_time < 500ms"
# GitHub Actions - profilowanie przy każdym PR
# .github/workflows/blackfire.yml
name: Blackfire Performance Tests
on: [pull_request]
jobs:
blackfire:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Blackfire Build
uses: blackfireio/github-action@v1
with:
blackfire-server-id: ${{ secrets.BLACKFIRE_SERVER_ID }}
blackfire-server-token: ${{ secrets.BLACKFIRE_SERVER_TOKEN }}
blackfire-client-id: ${{ secrets.BLACKFIRE_CLIENT_ID }}
blackfire-client-token: ${{ secrets.BLACKFIRE_CLIENT_TOKEN }}
ref: ${{ github.head_ref }}
base-ref: main
Praktyczna sesja profilowania – przykład
# Krok 1: profil bazowy przed optymalizacją
blackfire curl https://magento2-dev.ddev.site/catalog/category/view/id/11
# Wynik: Wall Time 3.2s, 147 SQL queries, 82MB RAM
# Krok 2: zidentyfikuj problemy
# Blackfire pokazuje: CategoryCollection::load() - 89 queries
# Wszystkie przez getProductCount() w pętli - N+1!
# Krok 3: poprawka - eager loading przez join
# Zamiast: foreach($categories as $cat) { $cat->getProductCount(); }
# Użyj: $collection->addProductCount();
# Krok 4: profil po poprawce
blackfire curl https://magento2-dev.ddev.site/catalog/category/view/id/11
# Wynik: Wall Time 0.8s, 12 SQL queries, 54MB RAM - 4x szybciej!
# Krok 5: porównaj dwa profile
blackfire compare PROFILE_ID_BEFORE PROFILE_ID_AFTER
Podsumowanie
Blackfire zmienia podejście do optymalizacji wydajności – zamiast zgadywać gdzie jest problem, masz twarde dane. Instalacja w DDEV zajmuje kilka minut, a wyniki pierwszego profilowania Magento 2 często ujawniają N+1 queries albo zbędne renderowanie bloków które da się wyeliminować w godzinę i zaoszczędzić sekundy czasu odpowiedzi. Asercje wydajnościowe w CI/CD to warstwa ochronna przed regresją – nikt nie commituje kodu który spowalnia stronę o 50% bez automatycznego alarmu.
