12 puan yazan darjeeling 2026-01-31 | Henüz yorum yok. | WhatsApp'ta paylaş

Özet:

  • Python'un subprocess modülü ve psutil kütüphanesi, son 15 yıldır süreç sonlanmasını beklerken (wait()) sleep ile waitpid çağrılarını tekrarlayan verimsiz bir 'busy-loop polling' yöntemi kullanıyordu.
  • Bu yöntem gereksiz CPU wake-up'larına, pil tüketimine, süreç sonlanmasını algılamada gecikmeye (latency) yol açıyor ve çok sayıda süreci izlerken ölçeklenebilirlik açısından zayıf kalıyordu.
  • Son güncellemeyle birlikte Linux'ta pidfd_open() ve poll(), BSD/macOS'ta ise kqueue() kullanılarak gerçek bir 'olay tabanlı bekleme (event-driven waiting)' hayata geçirildi.
  • Windows zaten WaitForSingleObject kullandığı için burada bir değişiklik yok; ancak POSIX sistemlerde gereksiz context switching ortadan kalkıyor ve CPU kullanımı '0'a yakınsıyor.

Ayrıntılı özet:
1. 15 yıldır süren sorun: Busy-loop polling
Python 3.3'te subprocess.Popen.wait() için timeout parametresi eklendiğinden beri, Python standart kütüphanesi ve yaygın kullanılan psutil kütüphanesi süreç sonlanmasını beklemek için verimsiz bir yöntem kullanıyordu.

Önceki mantık basitti ama verimsizdi:

  1. waitpid(WNOHANG) ile süreç durumunu kontrol et (non-blocking)
  2. Süreç bitmediyse kısa süre sleep() yap (exponential backoff uygulanır)
    1. adıma dön ve tekrarla
# Önceki yöntem (kavramsal kod)  
import time, os  
  
def wait_busy(pid, timeout):  
    delay = 0.0001  
    while True:  
        # Sürecin bitip bitmediğini kontrol et (polling)  
        if os.waitpid(pid, os.WNOHANG) == (pid, status):  
            return status  
        time.sleep(delay)  
        delay = min(delay * 2, 0.040) # bekleme süresini en fazla 40ms'e kadar artır  
  

Bu yöntemin 3 kritik dezavantajı var.

  • CPU wake-up'ları: Bekleme süresi artırılsa bile sistemin durumu kontrol etmek için periyodik olarak uyanması gerekir; bu da CPU çevrimlerini boşa harcar ve enerji tüketir.
  • Latency (gecikme): Sürecin gerçekten sonlandığı an ile sleep'ten uyanılıp bunun algılandığı an arasında kaçınılmaz bir zaman farkı oluşur.
  • Scalability (ölçeklenebilirlik): Aynı anda yüzlerce ya da binlerce sürecin izlenmesi gereken sunucu ortamlarında bu ek yük hızla büyür.

2. Çözüm: POSIX sistemler için olay tabanlı bekleme (Event-driven Waiting)
Tüm POSIX sistemleri, dosya tanımlayıcılarının (file descriptor) durum değişimlerini algılamak için mekanizmalar (select, poll, epoll, kqueue) sunar. Python ve psutil, yakın zamanda bunu süreç PID algılamasında kullanacak şekilde geliştirildi.

  • Linux: 2019'da Linux 5.3 çekirdeğine eklenen pidfd_open() sistem çağrısı kullanılıyor. Bu çağrı, süreç PID'sini işaret eden bir dosya tanımlayıcısı döndürüyor; bu tanımlayıcı poll() ya da epoll() içine kaydedilerek süreç sonlanma olayı izlenebiliyor. (os modülüne Python 3.9'dan itibaren eklendi)
  • BSD / macOS: Süreç olaylarını verimli biçimde izlemek için kqueue() sistem çağrısının EVFILT_PROC filtresi kullanılıyor.
  • Windows: Zaten WaitForSingleObject API'si üzerinden olay tabanlı beklemeyi desteklediği için bir değişiklik yok.

3. Performans iyileştirmesi ve sonuçlar
Bu değişiklikle birlikte wait() çağrısı sırasında süreç, çekirdek açısından 'interruptible sleep' durumuna geçiyor. Yani CPU'yu hiç tüketmeden çekirdek alanında sessizce bekliyor ve süreç sonlanma sinyali geldiği anda hemen uyanıyor.

/usr/bin/time -v gibi araçlarla yapılan benchmark sonuçlarına göre, önceki yönteme kıyasla gereksiz context switching dramatik biçimde azaldı ve süreç sonlanmasını algılama hızı da anında iyileşti. Bu güncelleme hem psutil kütüphanesine hem de CPython çekirdeğine yansıtıldı; böylece Python geliştiricileri ek bir kod değişikliği yapmadan performans artışından yararlanabilecek.

Henüz yorum yok.

Henüz yorum yok.