Post

%100 CPU Kullanan Ama Hiçbir Şey Yapmayan Programlar: strace'in Resmen Bittiği Yer

Sunucu fanları uçak gibi ötüyor, CPU %100'e vurmuş. Ama strace çalıştırdığınızda ekran bomboş. Neden? Kernel Space ile User Space arasındaki görünmez duvarı ve 'perf' aracıyla kodun zihnine girmeyi öğreniyoruz.

%100 CPU Kullanan Ama Hiçbir Şey Yapmayan Programlar: strace'in Resmen Bittiği Yer

Sistem yöneticisinin kabusu bazen sessizliktir, bazen de gürültüdür.

Sunucu odasına (veya laptopunuza) girdiğinizde o tanıdık sesi duyarsınız: Fanlar son devirde dönüyordur. Sanki bir uçak kalkışa hazırlanıyor gibidir. Terminale koşup top veya htop komutunu çalıştırırsınız. Ve karşınızda o suçluyu görürsünüz: En tepede, kırmızı renklerle parlayan, %100 CPU tüketen bir süreç (Process).

Refleksleriniz hemen devreye girer. Bugüne kadar öğrendiğiniz (ve önceki yazılarımızda anlattığımız) o süper kahramanı çağırırsınız: strace. “Bakalım bu haylaz arkada ne işler çeviriyor?” dersiniz. Komutu yazarsınız: strace -p <PID>

Ve… Hiçbir şey. Koca bir hiç. İmleç yanıp söner. Ekrana ne bir read, ne bir write, ne de bir futex düşer. Bazen çok nadiren, araya sıkışmış anlamsız bir gettimeofday düşer, sonra yine sessizlik.

Şimdi büyük bir paradoksla karşı karşıyasınız:

  1. top diyor ki: “Bu adam deliler gibi çalışıyor, ter döküyor, CPU’yu sömürüyor!”
  2. strace diyor ki: “Bu adam hiçbir şey yapmıyor, parmağını bile kıpırdatmıyor.”

Kim yalan söylüyor? Cevap: İkisi de doğru söylüyor. Sorun, sizin baktığınız yerde. Bugün, strace mikroskobunu çöpe atıp, perf (Linux Profiling Tools) cihazını elimize alacağımız gündür. Çünkü sorun artık Kernel’da (Devlet Dairesi) değil, uygulamanın kendi beyninin (User Space) içinde.

🧱 1. Duvarın Ötesi: User Space vs Kernel Space

Bu serideki ilk analojimizi hatırlayın: Program (Vatandaş) ve Kernel (Devlet Memuru/Arşivci).

strace sadece ve sadece, vatandaşın memurdan bir şey istediği anı (System Call) kaydeder.

  • “Dosya ver” (read)
  • “Ağa bağlan” (connect)
  • “Saati söyle” (time)

Ama eğer vatandaş, kendi evine kapanıp, perdeleri çekip, kendi kendine matematik problemi çözmeye başlarsa? Veya bir kağıdı alıp üzerine sonsuza kadar “A” harfi yazıp silerse? Memur (Kernel) bundan haberdar olabilir mi? Hayır. Memur sadece kapı çalındığında iş yapar. Vatandaş kapıyı çalmıyorsa, memur (ve dolayısıyla strace) kördür.

İşte CPU Bound (İşlemci Odaklı) işlemler tam olarak budur. Program, dış dünyadan (Disk, Ağ) hiçbir şey istemez. Sadece işlemci (ALU) üzerinde aritmetik veya mantıksal işlemler yapar.

strace bu noktada biter. Artık Profiling (Profil Çıkarma) dünyasına hoş geldiniz.

🔬 2. Yeni Silahımız: perf (Linux Profiling Tool)

Eğer strace bir güvenlik kamerasıysa (kapıdan gireni çıkanı izler), perf bir zihin okuyucudur (beynin hangi bölgesinin aktif olduğunu izler).

perf, Linux çekirdeğinin içine gömülü bir performans analiz aracıdır. Çalışma mantığı Sampling (Örnekleme) üzerinedir:

  1. Saniyede (örneğin) 1000 kez CPU’yu durdurur (Interrupt).
  2. O an CPU’nun hangi Instruction Pointer (IP) adresinde (yani kodun hangi satırında) olduğuna bakar.
  3. Bunu kaydeder ve CPU’yu devam ettirir.

Bu işlemi yeterince uzun süre yaparsanız, istatistiksel olarak programın vaktini en çok nerede harcadığını %99 doğrulukla bulursunuz.

Kurulum (Eğer Yoksa)

Çoğu minimal sistemde gelmez.

1
2
3
4
5
# Ubuntu/Debian
sudo apt install linux-tools-common linux-tools-generic linux-tools-$(uname -r)

# RHEL/CentOS/Fedora
sudo yum install perf

🎥 3. Canlı İzleme: perf top

Hadi şu %100 CPU yiyen hayalet süreci yakalayalım. Komutumuz tipk top gibidir, ama fonksiyonları gösterir:

1
sudo perf top -p <PID>

(Eğer PID vermezseniz tüm sistemi izler).

Karşınıza şöyle bir ekran çıkacaktır:

1
2
3
4
5
Samples: 45K of event 'cycles', Event count (approx.): 123456789
Overhead  Shared Object       Symbol
  95.50%  my_bad_program      [.] heavy_calculation_function
   2.10%  libc-2.31.so        [.] _int_malloc
   0.50%  [kernel]            [k] do_syscall_64

Bu Tabloyu Nasıl Okuruz?

  1. Overhead: İşlemcinin harcadığı vaktin yüzdesi. %95.50 çok ciddi bir rakam.
  2. Shared Object: Bu kod nerede? my_bad_programın kendisinde mi, yoksa çağırdığı bir kütüphanede (libc, libssl) mi?
  3. Symbol: Fonksiyonun adı. İşte suçlu burada: heavy_calculation_function.

Artık sorunun diskte, ağda veya kernel’da olmadığını biliyorsunuz. Sorun, yazılımcının yazdığı heavy_calculation_function isimli fonksiyonda.

🕵️‍♂️ 4. Vaka Analizi: “Sonsuz Döngü” (Infinite Loop)

Bir Python scripti yazdınız ama yanlışlıkla sonsuz döngüye soktunuz.

1
2
3
4
5
6
7
# bad_loop.py
def hesapla():
    i = 0
    while True:
        i = i + 1  # Sonsuza kadar topla

hesapla()

Bunu çalıştırın. Bir çekirdeği %100 kullanacaktır. strace -p <PID> yapın. Ekran bomboş olacaktır. Çünkü i + 1 işlemi Kernel’ı ilgilendirmez. Tamamen CPU ve RAM (Register) arasında döner.

Şimdi perf top -p <PID> yapın:

1
2
3
Overhead  Shared Object       Symbol
  40.00%  python3.8           [.] _PyEval_EvalFrameDefault
  20.00%  python3.8           [.] PyLong_FromLong

Gördünüz mü? Python yorumlayıcısının (_PyEval_EvalFrameDefault) sürekli çalıştığını yakaladınız. Bu, kodun sürekli bir döngüde “yorumlandığını” (execute edildiğini) kanıtlar.

💡 İpucu: Derlenen dillerde (C/C++, Go, Rust) fonksiyon adını net görürsünüz. Yorumlanan dillerde (Python, Ruby, Java) ise genellikle o dilin sanal makinesinin (VM) fonksiyonlarını görürsünüz (Örn: JVM, V8, PyEval). Daha derin analiz için o dillere özel profiler’lar (py-spy, async-profiler) gerekebilir ama perf size “Sorun CPU Bound” teşhisini koydurur.

🧬 5. Vaka Analizi: “Deli Gibi Şifreleme” (Crypto Mining veya SSL)

Bazen sunucunuz hacklenmiştir ve bir Crypto Miner çalışıyordur. Veya uygulamanız yanlışlıkla sürekli SSL Handshake yapıyordur. perf top çıktısında şunları görürseniz tetikte olun:

1
2
3
Overhead  Symbol
  80.12%  sha256_transform_avx2
  10.05%  aes_encrypt_block

sha256, md5, aes, gzip gibi kelimeler görüyorsanız, işlemci Matematiksel Hesaplama ile meşguldür.

  • Bu beklenen bir şey mi? (Video işleme, sıkıştırma sunucusu?)
  • Yoksa beklenmedik bir şey mi? (Hacklenme, sonsuz şifreleme döngüsü?)

strace bunu asla gösteremezdi. Çünkü şifreleme, saf matematiktir ve User Space’te yapılır.

🛠️ 6. “Symbol not found” (Hex Adresler) Sorunu

Bazen perf top çalıştırırsınız ve fonksiyon isimleri yerine sadece anlamsız Hex adresler görürsünüz:

1
2
3
Overhead  Symbol
  60.00%  0x0000000004f2a1
  30.00%  0x0000000004f2b5

Bunun sebebi, kullandığınız programın “Stripped” (Sembollerinden arındırılmış) olmasıdır. Derlenirken debug sembolleri (isim etiketleri) silinmiştir. Production ortamlarında bu normaldir (Dosya boyutu küçülsün diye).

Çözüm: Eğer bu bir sistem paketi ise (örn: nginx, libc), o dağıtımın Debug Info paketlerini kurmanız gerekir.

  • Ubuntu: nginx-dbgsym, libc6-dbgsym
  • CentOS: debuginfo-install glibc

Bu paketleri kurduğunuzda perf, o hex adreslerin hangi fonksiyona denk geldiğini haritalayabilir.

🔥 7. İleri Seviye: Flame Graphs (Alev Grafikleri)

perf top anlık izleme için harikadır ama raporlamak zordur. Patronunuza “Bak burada yüzde 90 yazıyor” demek yerine, havalı ve renkli bir grafik göstermek isterseniz dünyaca ünlü Flame Graph (Brendan Gregg) tekniğini kullanmalısınız.

Mantık basittir:

  1. perf record: Veriyi 10-20 saniye boyunca diske kaydet.
  2. perf script: Kaydı okunabilir metne çevir.
  3. FlameGraph.pl: Metni grafiğe çevir (SVG).

Sonuçta oluşan grafik, fonksiyonların birbirini çağırma hiyerarşisini (Stack Depth) ve harcadığı zamanı (Width) gösterir. En geniş bar, en suçlu fonksiyondur.

🚦 Özet: Araç Seçim Rehberi (Cheat Sheet)

Kafalar karışmasın. Hangi durumda hangi aracı çekeceksiniz?

Belirti (Semptom)Olası SorunDoğru Araç
CPU %0, Program BekliyorNetwork, Disk, Kilit (Lock)strace (Kraldır)
CPU %100, Fan Sesi VarSonsuz Döngü, Hesaplamaperf (User Space)
CPU %3-5 ama yavaşKarışık (Hem I/O Hem CPU)İkisi de (strace -c + perf)
Memory ŞişiyorMemory Leakvalgrind, heaptrack

👋 Son Söz: Gözlemcinin Perspektifi

Bu blog serisinde, Linux sistem programlamanın en derinlerine indik.

  • open/read ile dosyalara dokunduk.
  • connect/bind ile ağ kablolarına girdik.
  • epoll ile zamanı yönettik.
  • kill ile ölümü tanıdık.
  • Ve şimdi perf ile, bir programın “zihnine” (CPU Instruction’larına) girmeyi öğrendik.

strace dış dünyayla olan ilişkiyi, perf ise iç dünyadaki çalkantıyı gösterir. Usta bir sistemci, elindeki çekicin her çiviye uymayacağını bilen, alet çantasındaki her aletin sınırlarını bilen kişidir.

Gördüğünüz gibi, “Neden çalışmıyor?” sorusunun tek bir cevabı yok. Ama doğru aleti, doğru zamanda kullandığınızda, cevabı bulamamanız imkansız.

Serimiz burada (şimdilik) sona eriyor. Ama Linux devasa bir okyanus. Öğrendiğiniz bu temel prensipler (Kernel Space, User Space, Syscall, Signal, Interrupt), karşınıza çıkacak en karmaşık Kubernetes, Docker veya Cloud sorunlarında bile feneriniz olacak.

Sorunsuz kernel’lar, düşük latency’ler ve temiz loglar dileğiyle. Ve unutmayın: Her şey bir dosyadır, süreçler fanidir, ama loglar (eğer disk dolmazsa) kalıcıdır.

This post is licensed under CC BY 4.0 by the author.