Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX PERF 2026

Perf & Flamegraph
Linux CPU Profiling

PMU donanım sayaçlarından flamegraph görselleştirmesine — perf ile CPU hotspot analizi, cache miss tespiti ve gömülü ARM sistemlerde profiling.

00 perf nedir

perf (perf_events), Linux kernel'ının içine entegre edilmiş performans analiz altyapısıdır. Donanım PMU sayaçlarından yazılım tracepoint'lerine kadar geniş bir ölçüm yelpazesi sunar.

PMU — Performance Monitoring Unit

Modern işlemcilerin tamamında PMU (Performance Monitoring Unit) adı verilen özel donanım bloğu bulunur. PMU, cycle sayımı, instruction retire, önbellek isabet/kaçırma, dal tahmini ve çok daha fazlası gibi düşük overhead'lı donanım sayaçlarını tutar. Intel PMU, AMD PMU ve ARM PMU (Cortex-A PMUv3) aynı kavramsal çerçeveyi paylaşır; ancak destekledikleri event'ler platform bağımlıdır.

Uygulama kodu → işlemci → PMU sayaçları → perf_event subsystem → ring buffer → userspace perf aracı

perf_event subsystem

Linux kernel 2.6.31 ile eklenen perf_event subsystem, PMU donanımını bir soyutlama katmanı arkasına saklar. Üç temel ölçüm modu sunar:

Counting moduBelirli bir zaman diliminde event sayısını tutar — perf stat bu modu kullanır, overhead minimumdur
Sampling moduEvent sayacı overflow olduğunda CPU'nun o anki IP (instruction pointer) ve stack'ini kaydeder — perf record
Tracepoint moduKernel statik tracepoint'lerine veya kprobe/uprobe dinamik noktalara bağlanır — perf trace

Event türleri

TürKaynakÖrnek event'ler
HardwarePMU donanımıcpu-cycles, instructions, cache-misses, branch-misses
SoftwareKernel yazılımıcpu-clock, task-clock, page-faults, context-switches
Tracepointftrace altyapısısched:sched_switch, kmem:kmalloc, block:block_rq_issue
Hardware cachePMU önbellek sayaçlarıL1-dcache-load-misses, LLC-load-misses, dTLB-misses
PMU rawCPU spesifik ham eventr0xXXXX — Intel/AMD/ARM'a özel event kodu

Kurulum ve yetki

bash — kurulum
# Ubuntu/Debian
sudo apt install linux-tools-$(uname -r) linux-tools-common

# Fedora/RHEL
sudo dnf install perf

# Sürüm kontrolü
perf version
# perf version 6.1.0

# Kernel paranoid seviyesi — perf'e izin ver (kalıcı için /etc/sysctl.conf)
sudo sysctl kernel.perf_event_paranoid=-1
sudo sysctl kernel.kptr_restrict=0

# Desteklenen event'leri listele
perf list
perf list hardware
perf list cache
NOT

kernel.perf_event_paranoid=2 (varsayılan) yalnızca root'a izin verir. Değer -1 yapıldığında tüm kullanıcılar PMU'ya erişebilir. Üretim sistemlerinde güvenlik açısından değerlendirin; CI/CD ve geliştirme makinelerinde -1 pratiktir.

Bu bölümde

  • PMU: işlemcide donanım sayaçları — döngü, instruction, cache miss, branch miss
  • perf_event subsystem: PMU'yu soyutlar; counting, sampling, tracepoint modları
  • Event türleri: hardware, software, tracepoint, cache, raw PMU
  • Kurulum: linux-tools paketi; paranoid sysctl ile kullanıcı izni

01 perf stat — temel sayaçlar

perf stat, counting modunda çalışır: program boyunca PMU sayaçlarını toplar ve sonunda özet istatistikleri gösterir. Overhead son derece düşüktür.

Temel kullanım

bash — perf stat temel
# Bir komutu ölç
perf stat ls -la /usr

# Çalışan bir sürece bağlan (PID)
perf stat -p 1234

# N saniye boyunca ölç
perf stat -p 1234 -- sleep 10

# Çıktı örneği:
#  Performance counter stats for 'ls -la /usr':
#
#        3,241,847      cycles                    #    3.241 GHz
#        4,108,523      instructions              #    1.27  insn per cycle
#          128,491      cache-references
#           12,304      cache-misses              #    9.58% of all cache refs
#           68,423      branch-instructions
#            1,203      branch-misses             #    1.76% of all branches
#
#        0.001063 seconds time elapsed

IPC hesabı ve anlam

IPC (Instructions Per Cycle), işlemcinin verimliliğinin temel ölçütüdür. Modern out-of-order işlemcilerde ideal IPC 3–5 civarındadır. Düşük IPC'nin üç ana nedeni vardır:

Memory bound (IPC < 1)Cache miss oranı yüksek — veri belleğini bekliyor; veri erişim kalıbını optimize et, önbellek dostu yapılar kullan
Branch misprediction (IPC 1-2)Şube tahmin birimleri yanlış tahmin yapıyor; pipeline flush oluyor — öngörülemeyen dalları azalt
Compute bound (IPC > 3)İşlemci kapasitesini kullanıyor — vektörize (SIMD) edilemeyenler için normal; bu aslında iyi bir durum

Özel event seçimi (-e)

bash — perf stat -e ile özel event
# Birden fazla event aynı anda
perf stat -e cycles,instructions,cache-misses,branch-misses ./my_program

# L1 ve LLC cache detayları
perf stat -e L1-dcache-loads,L1-dcache-load-misses,LLC-loads,LLC-load-misses ./my_program

# TLB miss'leri
perf stat -e dTLB-loads,dTLB-load-misses,iTLB-loads,iTLB-load-misses ./my_program

# Tracepoint ile birlikte (page fault sayısı)
perf stat -e cycles,page-faults ./my_program

# Tüm CPU'lar için sistem geneli (-a)
perf stat -a -e cycles,instructions -- sleep 5

# CSV çıktısı — otomasyon için
perf stat --field-separator , -e cycles,instructions ./my_program

Tekrarlı ölçüm (-r)

bash — istatistiksel güvenilirlik
# 5 kez çalıştır, ortalama ve standart sapma göster
perf stat -r 5 ./my_program

# Çıktıda varyasyon yüzdesi görülür:
#   3,241,847 +- 0.82%  cycles
# Varyasyon %5'ten büyükse ölçüm güvenilir değil — sistem gürültüsü var

# CPU frekans scaling'i kapat (daha kararlı ölçüm)
sudo cpupower frequency-set -g performance
# ya da
echo performance | sudo tee /sys/devices/system/cpu/cpu*/cpufreq/scaling_governor
İPUCU

Üretim sunucularında veya gömülü hedeflerde ölçüm yaparken CPU frekans yönetimini kontrol edin. ARM Cortex-A işlemcilerde cpufreq driver'ı ve thermal throttling, ölçüm varyansını artırır. Kıyaslama öncesi performance governor'a geçin.

Bu bölümde

  • perf stat: counting modu — düşük overhead, program sonu özeti
  • IPC = instructions / cycles; <1 memory bound, >3 compute bound
  • -e event1,event2 ile özel sayaç seçimi
  • -r N ile tekrarlı ölçüm ve istatistiksel güven aralığı

02 perf record — örnekleme

perf record, sampling modunda çalışır: belirli aralıklarla CPU'nun o anki instruction pointer'ını ve call stack'ini kaydeder. Bu veri hangi fonksiyonların en çok CPU kullandığını ortaya çıkarır.

Temel kayıt

bash — perf record temel
# Komutu başlat ve kaydet (varsayılan: -F 4000 — saniyede 4000 örnek)
perf record ./my_program

# Örnekleme frekansını belirle (-F Hz)
perf record -F 99 ./my_program          # 99 Hz — düşük overhead
perf record -F 9999 ./my_program        # 9999 Hz — yüksek çözünürlük

# Çalışan sürece bağlan
perf record -p 1234 -F 99 -- sleep 30

# Tüm CPU'lar, sistem geneli
perf record -a -F 99 -- sleep 30

# Kayıt perf.data dosyasına yazılır
ls -lh perf.data

Call graph kaydı (--call-graph)

Flamegraph oluşturabilmek için call graph kaydı şarttır. Üç yöntem mevcuttur:

YöntemKomutGereksinimArtı / Eksi
Frame Pointer (fp)--call-graph fp-fno-omit-frame-pointer ile derlemeDüşük overhead; derleyici optimizasyonuyla uyumsuz olabilir
DWARF--call-graph dwarfDebug sembolü (-g)Doğru stack unwinding; yüksek overhead, büyük perf.data
LBR (Last Branch Record)--call-graph lbrIntel Haswell+ (LBR donanımı)En düşük overhead; sığ call stack (32 frame)
bash — call graph kayıt örnekleri
# Frame pointer yöntemi — derleme gerektirir
gcc -O2 -fno-omit-frame-pointer -o my_program my_program.c
perf record -F 99 --call-graph fp -g ./my_program

# DWARF yöntemi — kaynak dizin bilgisiyle
gcc -O2 -g -o my_program my_program.c
perf record -F 99 --call-graph dwarf ./my_program

# LBR (Intel'e özgü)
perf record -F 99 --call-graph lbr ./my_program

# perf.data dosyasını belirt (-o)
perf record -o profile_run1.data -F 99 --call-graph fp ./my_program

# Build-id kaydetme — taşınabilirlik için (varsayılan açık, devre dışı bırakmak)
perf record --no-buildid -F 99 ./my_program

Event bazlı örnekleme

bash — event-driven sampling
# Cache miss'lerde örnekle (PEBS — Intel Precise Event)
perf record -e cache-misses:p --call-graph fp ./my_program

# Branch miss'lerde örnekle
perf record -e branch-misses:p --call-graph fp ./my_program

# Belirli CPU'da çalıştır
perf record -C 0,1 -F 99 --call-graph fp ./my_program

# Yalnızca kernel alanını profille
perf record -F 99 -k --call-graph fp -- sleep 10

# Yalnızca kullanıcı alanını profille
perf record -F 99 -u --call-graph fp ./my_program

Bu bölümde

  • perf record: sampling — her N event'te IP + call stack kaydı
  • -F Hz: örnekleme frekansı — 99 Hz hafif, 9999 Hz yüksek çözünürlük
  • --call-graph fp|dwarf|lbr: flamegraph için call stack zorunlu
  • fp: düşük overhead, -fno-omit-frame-pointer gerekli; dwarf: doğru ama ağır

03 perf report — analiz

perf report, perf.data dosyasını okur ve hangi fonksiyonların CPU zamanını tükettiğini gösterir. TUI (terminal arayüzü) ve --stdio düz metin modu sunar.

TUI — interaktif analiz

bash — perf report TUI
# Varsayılan: TUI arayüzü açılır
perf report

# Belirli bir dosya için
perf report -i profile_run1.data

# TUI tuş kısayolları:
# Enter  — seçili fonksiyonu genişlet / caller'larını göster
# a      — annotate: assembly ile CPU zamanı dağılımı
# d      — DSO (dynamic shared object) filtrele
# t      — thread filtrele
# /      — regex ile arama
# q      — çıkış

--stdio modu

bash — perf report stdio
# Düz metin çıktısı — betik ve CI için ideal
perf report --stdio

# Çıktı örneği:
# Overhead  Command  Shared Object       Symbol
# ........  .......  ..................  ......................................
#   34.21%  my_prog  my_program          [.] process_data
#   18.45%  my_prog  libc.so.6           [.] __memcpy_avx_unaligned
#   12.33%  my_prog  my_program          [.] hash_lookup
#    9.01%  my_prog  [kernel]            [k] copy_user_generic_string

# Sıralama kriterini değiştir
perf report --stdio --sort dso,symbol
perf report --stdio --sort cpu,pid,symbol

# Çağıran/çağrılan zinciri göster
perf report --stdio --call-graph callee --max-stack 5

# Kernel sembolleri dahil et
perf report --stdio -k /path/to/vmlinux

Inline fonksiyon görünürlüğü

Compiler optimizasyonuyla inline hale getirilen fonksiyonlar varsayılan raporda görünmez. Debug sembolleriyle bu sorun çözülür:

bash — inline fonksiyon analizi
# -g ile derleme inline fonksiyonları görünür yapar
gcc -O2 -g -fno-omit-frame-pointer -o my_prog my_prog.c

# --inline seçeneği ile satır seviyesi inline bilgisi
perf report --stdio --inline

# Hotspot fonksiyonu filtrele
perf report --stdio --dsos my_program --symbols process_data

Bu bölümde

  • TUI: interaktif navigasyon; Enter ile genişlet, 'a' ile annotate
  • --stdio: betik dostu düz metin çıktısı
  • --sort dso,symbol: kütüphane veya sembol bazlı sıralama
  • --inline: derleyici optimize ettiği inline fonksiyonları göster

04 perf script + flamegraph

Flamegraph, call stack örneklerini görsel olarak sunar: en geniş dikdörtgen en çok CPU tüketen fonksiyonu temsil eder. Brendan Gregg'in geliştirdiği araç seti perf script çıktısını SVG'ye çevirir.

Araç kurulumu

bash — flamegraph araçları
# FlameGraph araçlarını indir (Brendan Gregg)
git clone https://github.com/brendangregg/FlameGraph.git
export FLAMEGRAPH_DIR=~/FlameGraph

# PATH'e ekle
export PATH=$PATH:$FLAMEGRAPH_DIR

Tam iş akışı

bash — perf → flamegraph iş akışı
# Adım 1: call graph ile kaydet
perf record -F 99 --call-graph fp -g ./my_program

# Adım 2: perf.data → okunabilir stack trace metni
perf script > out.perf

# out.perf formatı (her sample):
# my_program 12345 1234.567890:     10203 cpu-clock:
#         400abc process_data+0x12 (/home/user/my_program)
#         400def main+0x45 (/home/user/my_program)

# Adım 3: stack'leri çöz ve say (stackcollapse)
stackcollapse-perf.pl out.perf > out.folded

# out.folded formatı (tek satır per stack):
# main;process_data;memcpy 42

# Adım 4: SVG oluştur
flamegraph.pl out.folded > flamegraph.svg

# Tarayıcıda aç
xdg-open flamegraph.svg

Tek komut zinciri

bash — tek satır pipeline
# Kaydet + çevir + görselleştir — her şey bir arada
perf record -F 99 --call-graph fp ./my_program && \
perf script | \
stackcollapse-perf.pl | \
flamegraph.pl > flamegraph.svg

# CPU türü renkli flamegraph
flamegraph.pl --color java out.folded > flamegraph.svg
flamegraph.pl --color io   out.folded > flamegraph_io.svg

# Başlık ve genişlik özelleştir
flamegraph.pl \
  --title "my_program CPU Profile" \
  --width 1600 \
  --minwidth 0.5 \
  out.folded > flamegraph.svg

SVG okuma

X ekseni (genişlik)Fonksiyonun toplam CPU zamanı oranı — geniş kutu = çok CPU tüketiyor
Y ekseni (yükseklik)Call stack derinliği — alt = üst fonksiyon (main), üst = yaprak (gerçek iş yapan)
RenkVarsayılan rastgele (aynı fonksiyon her çalıştırmada farklı renk); --color ile anlamlı renk atanabilir
TıklanabilirSVG interaktif — fonksiyona tıklayınca o alt ağaç zoom'lanır; Ctrl+F ile fonksiyon ara

Diferansiyel flamegraph

bash — optimizasyon öncesi/sonrası karşılaştırma
# Optimizasyon öncesi
perf record -F 99 --call-graph fp -o before.data ./v1_program
perf script -i before.data | stackcollapse-perf.pl > before.folded

# Optimizasyon sonrası
perf record -F 99 --call-graph fp -o after.data ./v2_program
perf script -i after.data | stackcollapse-perf.pl > after.folded

# Diferansiyel SVG — mavi: azalan, kırmızı: artan CPU
difffolded.pl before.folded after.folded | flamegraph.pl > diff.svg

Bu bölümde

  • Flamegraph pipeline: perf record → perf script → stackcollapse-perf.pl → flamegraph.pl → SVG
  • X ekseni = CPU zamanı oranı; Y ekseni = call stack derinliği
  • SVG interaktif: tıkla zoom, Ctrl+F ara
  • difffolded.pl ile öncesi/sonrası karşılaştırma

05 perf annotate — assembly analizi

perf annotate, kaynak kodu ve assembly satırlarına CPU zamanının nasıl dağıldığını gösterir. Hangi assembly instruction'ın en çok zaman harcadığını bulmak için idealdir.

Temel annotate

bash — perf annotate
# perf.data üzerinde annotate (TUI açılır)
perf annotate

# Belirli bir fonksiyonu annotate et
perf annotate process_data

# Düz metin çıktısı
perf annotate --stdio process_data

# Kaynak + assembly karışık görünüm (-d)
perf annotate --stdio -d process_data

# Sembol dosyası belirt
perf annotate --stdio --symfs /path/to/debug/symbols process_data

Assembly çıktısını okuma

perf annotate çıktı örneği
; process_data fonksiyonu assembly görünümü
; Sol sütun: o instruction'a düşen CPU zamanı yüzdesi

         :   void process_data(int *arr, int n) {
         :       int sum = 0;
    0.12 :   400abc:  xor    %eax,%eax
         :       for (int i = 0; i < n; i++) {
   45.33 :   400abe:  mov    (%rdi,%rcx,4),%edx   <-- L1 cache miss burada!
    0.45 :   400ac2:  add    %edx,%eax
    0.08 :   400ac4:  inc    %rcx
    0.22 :   400ac6:  cmp    %rsi,%rcx
    0.11 :   400ac9:  jl     400abe
         :   }

Yukarıdaki örnekte mov (%rdi,%rcx,4),%edx instruction'ı zamanın %45'ini alıyor — bu bellek erişiminin cache miss'e yol açtığının klasik işaretidir. CPU belleği bekliyor.

Cache thrashing tespiti

bash — cache miss odaklı profil
# Cache miss event'leriyle örnekle (PEBS precision)
perf record -e cache-misses:pp --call-graph fp ./my_program

# Annotate: hangi instruction'da cache miss oluyor
perf annotate --stdio

# Daha ayrıntılı: L1 dcache load miss
perf record -e L1-dcache-load-misses:pp --call-graph fp ./my_program
perf report --stdio

Bu bölümde

  • perf annotate: assembly satır bazında CPU zaman dağılımı
  • Yüksek yüzdeli mov instruction → bellek erişim gecikmesi → cache miss
  • -e cache-misses:pp ile precision sampling — PEBS destekli Intel'de daha doğru
  • Kaynak + assembly karışık görünüm için -g ile derleme gerekli

06 Donanım event'leri

PMU donanımı çok sayıda granüler event sunar. Doğru event seçimi mikro-mimari darboğazları tespit etmeyi kolaylaştırır.

Cache event'leri

bash — cache analizi
# L1-L2-L3 önbellek hiyerarşisi analizi
perf stat -e \
  L1-dcache-loads,L1-dcache-load-misses,\
  L2-loads,L2-load-misses,\
  LLC-loads,LLC-load-misses \
  ./my_program

# Instruction cache miss (kod boyutu büyük uygulamalar için önemli)
perf stat -e L1-icache-load-misses ./my_program

# Store miss (write-heavy workload)
perf stat -e L1-dcache-stores,L1-dcache-store-misses ./my_program

Branch event'leri

bash — branch analizi
# Branch prediction analizi
perf stat -e \
  branch-instructions,branch-misses,\
  branches,branch-misses \
  ./my_program

# Branch miss oranını hesapla:
# %miss = branch-misses / branch-instructions * 100
# >5% yüksek kabul edilir

TLB event'leri

bash — TLB analizi
# TLB miss — sanal-fiziksel adres çevirisi başarısız
perf stat -e \
  dTLB-loads,dTLB-load-misses,\
  iTLB-loads,iTLB-load-misses \
  ./my_program

# Yüksek TLB miss → hugepage kullanmayı düşün
sudo sysctl vm.nr_hugepages=512
# veya transparent hugepage
echo always > /sys/kernel/mm/transparent_hugepage/enabled

Intel PEBS (Precise Event-Based Sampling)

Intel Haswell ve sonrası, PEBS ile instruction-level precision sağlar. Normal sampling'de ±birkaç instruction kayması olabilir; PEBS ile tam instruction yakalanır.

bash — PEBS precision sampling
# :p — yazılım precise (en iyi çaba)
perf record -e cycles:p --call-graph fp ./my_program

# :pp — PEBS hardware precise (Intel)
perf record -e cycles:pp --call-graph fp ./my_program

# :ppp — maximum precision (sadece belirli event'ler)
perf record -e mem-loads:ppp --call-graph fp ./my_program

# AMD IBS (Instruction-Based Sampling) — AMD eşdeğeri
perf record -e ibs_op/cnt_ctl=1/ --call-graph fp ./my_program

ARM PMUv3 (Cortex-A)

bash — ARM PMU event'leri
# ARM Cortex-A PMUv3 desteklenen event'ler
perf list | grep -i arm

# ARM ham PMU event'leri (r0x0001 = SW_INCR, r0x0011 = CPU_CYCLES, vb.)
# ARMv8 PMUv3 event tablosu: ARM Architecture Reference Manual bakın

# Cortex-A72 üzerinde temel profil
perf stat -e cycles,instructions,cache-misses ./my_program

# ARM özel: L1I cache refill
perf stat -e r0001 ./my_program   # SW_INCR — yazılım artırımı
perf stat -e r0014 ./my_program   # L1I_CACHE_REFILL
perf stat -e r0003 ./my_program   # L1D_CACHE_REFILL

Bu bölümde

  • Cache hierarchy: L1/L2/LLC load-misses — hangi seviyede takılıyor
  • Branch miss %5+ → prediction sorunları; veri bağımlı dallardan kaçın
  • TLB miss yüksekse → hugepage (2M/1G) kullanımını değerlendir
  • Intel PEBS :pp — instruction-accurate sampling; ARM PMUv3 ham event kodu rXXXX

07 Geniş ekosistem: sched / lock / mem

perf, CPU profilinin ötesinde zamanlama, kilit çakışması ve bellek erişim analizi gibi spesifik alt sistemler için de araçlar sunar.

perf sched — zamanlama analizi

bash — perf sched
# Zamanlama event'lerini kaydet
perf sched record -- sleep 10

# Özet istatistikler: her task için gecikme
perf sched latency

# Çıktı örneği:
# Task              |   Runtime ms  | Switches | Average delay ms | Maximum delay ms
# my_program:1234   |    1234.567   |     892  |         0.123    |        12.456

# Timeline görünümü
perf sched timehist

# Replay (zamanlama simülasyonu)
perf sched replay

perf lock — kilit çakışması

bash — perf lock
# Kilit event'lerini kaydet (kernel CONFIG_LOCKDEP gerekebilir)
perf lock record -a -- sleep 10

# Kilit çakışma raporu
perf lock report

# Çıktı örneği:
#                      Name   acquired  contended  avg-wait(ns)  max-wait(ns)
# &rq->lock                   123456      4567         234.5        89012.3

# Sadece çakışmalı kilitleri göster
perf lock report --key wait

perf mem — bellek erişim analizi

bash — perf mem
# Bellek load/store örnekleme (PEBS/IBS gerektirir)
perf mem record ./my_program

# Rapor: bellek erişim gecikme dağılımı
perf mem report

# Sadece yüklemeleri (loads) analiz et
perf mem record -t load ./my_program

# Gecikme bazlı sıralama
perf mem report --sort local_weight

Off-CPU analizi

Off-CPU profiling, CPU'da çalışmayan (engellenmiş, uyuyan) süreleri ölçer. Bu genellikle I/O bekleme, kilit bekleme veya zamanlayıcı gecikmeleridir.

bash — off-CPU profiling
# sched:sched_switch tracepoint ile off-CPU kayıt
perf record -e sched:sched_switch --call-graph dwarf -p 1234 -- sleep 30

# Off-CPU flamegraph oluştur (offcpufreq.awk ile)
perf script | \
  awk '/sched:sched_switch/ { ... }' | \
  flamegraph.pl --color io --title "Off-CPU" > offcpu.svg

# Daha kolay: BCC/eBPF offcputime aracı
sudo /usr/share/bcc/tools/offcputime -p 1234 10 | \
  flamegraph.pl > offcpu.svg

Bu bölümde

  • perf sched latency: zamanlama gecikmesi — real-time analizi için temel
  • perf lock report: en çok çakışan kilit ve ortalama bekleme süresi
  • perf mem record: bellek erişim gecikmesi ve önbellek düzeyi dağılımı
  • Off-CPU: sched_switch tracepoint veya BCC offcputime — engellenme nedenlerini bul

08 Pratik: cache miss → optimize → flamegraph

Gerçek bir optimizasyon senaryosu: cache-unfriendly döngü tespit et, veriyi yeniden düzenle, öncesi/sonrası flamegraph ile farkı gör.

Cache-unfriendly örnek program

C — cache_test.c (kötü sürüm)
/* cache_test.c — column-major erişim: cache miss yüksek */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define N 4096

int matrix[N][N];
long long sum_columns(void) {
    long long sum = 0;
    /* Sütun bazlı erişim: her satıra atlarken cache line atlanır */
    for (int col = 0; col < N; col++)
        for (int row = 0; row < N; row++)
            sum += matrix[row][col];    /* stride = N * sizeof(int) = 16384 byte */
    return sum;
}

int main(void) {
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            matrix[i][j] = i * N + j;
    printf("sum = %lld\n", sum_columns());
    return 0;
}
bash — kötü sürümü profille
gcc -O2 -fno-omit-frame-pointer -g -o cache_bad cache_test.c

# Temel istatistikler
perf stat -e cycles,instructions,LLC-load-misses,L1-dcache-load-misses ./cache_bad

# Flamegraph kayıt
perf record -F 99 --call-graph fp ./cache_bad
perf script | stackcollapse-perf.pl | flamegraph.pl > before.svg

Optimize edilmiş sürüm

C — cache_test_opt.c (iyi sürüm)
/* cache_test_opt.c — row-major erişim: cache dostu */
#include <stdio.h>
#define N 4096

int matrix[N][N];

long long sum_rows(void) {
    long long sum = 0;
    /* Satır bazlı erişim: ardışık bellek — cache line tam kullanımı */
    for (int row = 0; row < N; row++)
        for (int col = 0; col < N; col++)
            sum += matrix[row][col];    /* stride = sizeof(int) = 4 byte */
    return sum;
}

int main(void) {
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            matrix[i][j] = i * N + j;
    printf("sum = %lld\n", sum_rows());
    return 0;
}
bash — karşılaştırma
gcc -O2 -fno-omit-frame-pointer -g -o cache_good cache_test_opt.c

# Her iki sürümü ölç
perf stat -e cycles,instructions,LLC-load-misses ./cache_bad
perf stat -e cycles,instructions,LLC-load-misses ./cache_good

# Beklenen sonuç (yaklaşık):
# cache_bad:  ~8,000,000,000 cycles  ~64,000,000 LLC-misses  ~12 saniye
# cache_good: ~1,200,000,000 cycles     ~200,000 LLC-misses   ~0.8 saniye

# Flamegraph karşılaştırma
perf record -F 99 --call-graph fp -o after.data ./cache_good
perf script -i after.data | stackcollapse-perf.pl > after.folded

# Diferansiyel flamegraph
perf script -i before.data | stackcollapse-perf.pl > before.folded
difffolded.pl before.folded after.folded | flamegraph.pl > diff.svg

Kernel thread profiling

bash — kernel thread profili
# Kernel thread'leri listele
ps aux | grep '\[kworker\|ksoftirqd\|kswapd\]'

# kswapd profili (bellek baskısı altında)
sudo perf record -F 99 --call-graph fp -p $(pgrep kswapd0) -- sleep 30
sudo perf report --stdio -k /boot/vmlinux

# Sistem geneli kernel profili
sudo perf record -a -F 99 --call-graph fp -K -- sleep 30
sudo perf script | stackcollapse-perf.pl | flamegraph.pl > kernel.svg

perf overhead dikkat noktaları

DurumOverheadÖneri
perf stat (counting)%0–1Her zaman güvenli; üretimde de kullanılabilir
perf record -F 99%1–3Geliştirme ve üretim profili için makul
perf record -F 9999%5–15Kısa süreli analiz; üretimde dikkatli kullan
--call-graph dwarf%10–30Büyük stack'ler çok veri yazar; -F düşük tut
Tracepoint yoğun%5–50+Yüksek frekanslı tracepoint (scheduler) overhead'ı gizleyebilir

Bu bölümde

  • Column-major vs row-major: stride erişim LLC miss'i 300x artırabilir
  • perf stat → sorun var mı; perf record + flamegraph → nerede; perf annotate → hangi instruction
  • Kernel thread profili için -k /boot/vmlinux ile sembol dosyası gerekli
  • perf overhead: counting <%1; sampling 99 Hz ~%2; dwarf call-graph %10–30