Menu
Szybki wybór
Hosting Domeny VPS SSL Kalkulator Porównania FAQ
Aktywne kody
Wszystkie kody rabatowe

perf — profilowanie CPU i analiza wydajności na Linux

Opublikowano: 10 kwietnia 2026 · Kategoria: VPS

Serwer zjada 95% CPU, ale logi aplikacji wyglądają normalnie. Która funkcja powoduje bottleneck? Czy problem to brak danych w cache procesora, błędne przewidywanie skoków warunkowych, czy może wolne I/O? perf — narzędzie z jądra Linux — odpowiada na te pytania korzystając z hardware performance counters procesora, bez potrzeby modyfikacji kodu. Google i Netflix używają go codziennie do optymalizacji produkcyjnych systemów.

Instalacja i perf stat — szybki przegląd wydajności

# Ubuntu/Debian — zainstaluj linux-tools pasujące do kernela
sudo apt install linux-tools-$(uname -r) linux-tools-common -y
perf --version

# perf stat — podstawowe statystyki CPU
perf stat ls /usr

# Output:
# Performance counter stats for 'ls /usr':
#
#          1.234567      task-clock (msec)       # 0.456 CPUs utilized
#                 2      context-switches         # 0.001 M/sec
#                 0      cpu-migrations           # 0.000 M/sec
#               123      page-faults              # 0.100 M/sec
#         3,456,789      cycles                   # 2.800 GHz
#         2,890,123      instructions             # 0.84 insns per cycle  <--- IPC!
#           567,890      branches                 # 460.238 M/sec
#            23,456      branch-misses            # 4.13% of all branches
#

# Statystyki dla działającego procesu (-p PID)
perf stat -p $(pgrep php-fpm | head -1) sleep 10

# Własny zestaw liczników
perf stat -e cycles,instructions,cache-misses,cache-references,LLC-loads,LLC-load-misses \
  python3 benchmark.py

perf top — interaktywny profiler w czasie rzeczywistym

perf top działa jak htop ale na poziomie funkcji — pokazuje które funkcje w całym systemie lub konkretnym procesie zużywają najwięcej cykli CPU. Odświeża się co kilka sekund.

# Systemowy top funkcji (wymaga root)
sudo perf top

# Tylko dla konkretnego procesu
sudo perf top -p $(pgrep node | head -1)

# Przykładowy output:
# Samples: 4K of event 'cycles', 4000 Hz, Event count (approx.): 1234567890
#   Overhead  Shared Object     Symbol
#   --------  ----------------  -------------------------
#     45.32%  [kernel]          [k] schedule
#     23.18%  libc.so.6         [.] malloc
#     15.44%  myapp             [.] process_request
#      8.12%  libssl.so.3       [.] AES_encrypt
#      4.23%  [kernel]          [k] tcp_sendmsg

# Przydatne klawisz w trybie interaktywnym:
# 'a' - annotate (pokaż asm z hot path)
# 's' - sort by overhead
# 'f' - filter by name
# 'z' - zero counters (reset)

perf record i perf report — szczegółowa analiza

# Nagraj próbki z call graph (stack traces)
sudo perf record -g -p $(pgrep nginx | head -1) -- sleep 30
# Wynikowy plik: perf.data

# Analizuj interaktywnie (TUI)
sudo perf report -g

# Analizuj bez interakcji (dump do stdout)
sudo perf report --stdio | head -100

# Nagrywaj konkretne zdarzenie (LLC misses)
sudo perf record -e LLC-load-misses:u -g -p <PID> -- sleep 15
sudo perf report -g fractal

# Nagrywaj cały system przez N sekund
sudo perf record -a -g -F 99 -- sleep 30
# -a = all CPUs, -F 99 = 99 Hz sampling (bezpieczne dla prod)

# Nagrywaj tylko user-space (bez kernel frames)
sudo perf record -u -g ./myapp

FlameGraph — wizualizacja wyników

Raporty tekstowe perf są trudne do analizy przy głębokich call graphs. FlameGraph Brendana Gregga zamienia je w interaktywne wykresy SVG — szerokie kolumny to gorące ścieżki kodu.

# Pobierz FlameGraph scripts
git clone https://github.com/brendangregg/FlameGraph.git /opt/flamegraph

# Nagraj dane z call graph
sudo perf record -a -g -F 99 -- sleep 30

# Generuj FlameGraph SVG
sudo perf script | \
  /opt/flamegraph/stackcollapse-perf.pl | \
  /opt/flamegraph/flamegraph.pl > flamegraph.svg

# Otwórz w przeglądarce (lub pobierz przez scp)
python3 -m http.server 8888  # i wejdź na http://server-ip:8888/flamegraph.svg

# Filtruj tylko określone symbole
sudo perf script | \
  /opt/flamegraph/stackcollapse-perf.pl | \
  grep -v "^kernel" | \
  /opt/flamegraph/flamegraph.pl \
  --title "PHP-FPM CPU Profile" \
  --width 1400 > php-profile.svg

# Różnicowy FlameGraph (before vs after optymalizacji)
# 1. Nagraj before.data i after.data
# 2. perf script -i before.data | stackcollapse-perf.pl > before.txt
# 3. perf script -i after.data  | stackcollapse-perf.pl > after.txt
# 4. difffolded.pl before.txt after.txt | flamegraph.pl > diff.svg

Hardware counters — LLC misses i branch mispredictions

Counter Dobra wartość Problem gdy Przyczyna / naprawa
IPC (insns/cycle) > 2.0 < 1.0 Cache misses, branch mispredictions, memory-bound app
LLC-load-misses < 1% LLC-loads > 5% Zła lokalność danych — przepisz struktury danych (SoA zamiast AoS)
branch-misses < 1% > 3% Unpredictable branches — sortuj dane przed pętlą, użyj branchless patterns
cache-misses < 0.1% > 1% Brak lokalności L1/L2 — prefetching, zmiana algorytmu
context-switches Niskie Tysiące/sek Za dużo wątków względem CPU, spinlocki, I/O bound threads

Profilowanie PHP-FPM i Node.js

# PHP-FPM — wymaga PHP skompilowanego z --enable-frame-pointers
# Sprawdź czy jest wsparcie:
php -i | grep "frame pointers"
# lub sprawdź: readelf -s /usr/lib/php/... | grep frame

# Nagraj próbki dla master PHP-FPM
sudo perf record -g -F 99 -p $(pgrep -x php-fpm8.2 | head -1) -- sleep 30
sudo perf report --stdio | head -50

# Node.js — z mapowaniem JIT symbols
node --perf-basic-prof app.js &
NODE_PID=$!

sudo perf record -g -F 99 -p $NODE_PID -- sleep 30

# Zmerguj Node JIT map z perf symbols
sudo perf script --symfs /tmp | \
  /opt/flamegraph/stackcollapse-perf.pl | \
  /opt/flamegraph/flamegraph.pl > node-flame.svg

# Java — użyj async-profiler (nie wymaga frame pointers)
# wget https://github.com/async-profiler/async-profiler/releases/...
java -agentpath:/opt/async-profiler/lib/libasyncProfiler.so=start,event=cpu,file=profile.html app.jar

Porównanie narzędzi profilowania

Narzędzie Metoda Narzut Kiedy używać
perf Sampling (PMU) Niski (1-3%) Produkcja, CPU profiling, cache analysis
gprof Instrumentacja Wysoki (20-50%) Dev/test, wymaga recompile z -pg
Valgrind Callgrind Simulacja CPU Bardzo wysoki (10-50x) Dokładny cache analysis, tylko dev/test
async-profiler Sampling JVMTI Niski Java/Kotlin produkcja, bez safepoint bias
Py-Spy Sampling Python Minimalny Python produkcja, FlameGraph output
rbspy Sampling Ruby Minimalny Ruby on Rails produkcja

Najczęstsze pytania

Czym jest perf i do czego służy? +
perf to narzędzie profilowania wydajności wbudowane w jądro Linux (linux-tools). Pozwala zbierać dane z hardware performance counters procesora (IPC, LLC misses, branch mispredictions), śledzić wywołania systemowe (perf trace), profilować CPU sampling (perf record + perf report) i analizować gorące punkty kodu. Używane przez Google, Meta i Netflix do optymalizacji produkcyjnych systemów.
Co to jest FlameGraph i jak go wygenerować? +
FlameGraph to wizualizacja stosu wywołań jako flame chart — szerokie prostokąty to funkcje zajmujące dużo CPU. Twórcą jest Brendan Gregg (brendangregg.com/FlameGraphs). Generuje się go: (1) perf record -g ./myapp, (2) perf script | stackcollapse-perf.pl | flamegraph.pl > out.svg. Wynikowy SVG jest interaktywny — można klikać, przybliżać i szukać wzorców. Alternatywnie użyj speedscope.app (online) lub Hotspot GUI.
Jakie hardware counters warto monitorować? +
Kluczowe hardware performance counters: LLC-load-misses (Last Level Cache misses) — wskazują na problemy z cache locality danych; branch-misses — mispredictions powodują opróżnienie pipeline CPU; instructions i cycles — IPC (instructions per cycle) poniżej 1 to problem; cache-misses — ogólne miss rate pamięci podręcznej. Wysoki LLC-load-misses lub niski IPC to typowe przyczyny wąskich gardeł CPU w aplikacjach serwerowych.
Jak profilować PHP-FPM lub Node.js z perf? +
Dla PHP-FPM: kompiluj PHP z --enable-frame-pointers i użyj perf record -g -p $(pgrep php-fpm) -- sleep 30, potem perf report. Dla Node.js: uruchom z --perf-basic-prof (generuje /tmp/perf-NNN.map z mapowaniem symbolów), potem perf record -g node --perf-basic-prof app.js, perf report --symfs /tmp. Dla Java użyj async-profiler z narzędziem jvm-attach, który obsługuje JIT-compiled symbols. Bez frame pointers (domyślne w większości dystrybucji) uzyskasz niekompletne stosy.

Sprawdź oferty pasujące do tego scenariusza

Poniżej masz szybkie przejścia do ofert i stron z kodami rabatowymi tam, gdzie są dostępne.