12 poin oleh darjeeling 2026-01-31 | Belum ada komentar. | Bagikan ke WhatsApp

Ringkasan:

  • Selama 15 tahun terakhir, modul subprocess Python dan library psutil telah menggunakan pendekatan 'Busy-loop polling' yang tidak efisien saat menunggu proses berakhir (wait()), dengan mengulang sleep dan waitpid.
  • Pendekatan ini menimbulkan wake-up CPU yang tidak perlu, konsumsi baterai, masalah latensi dalam mendeteksi berakhirnya proses, dan skalabilitas yang buruk saat memantau banyak proses.
  • Melalui pembaruan terbaru, di Linux kini diterapkan 'penantian berbasis event (event-driven waiting)' yang sesungguhnya dengan memanfaatkan pidfd_open() dan poll(), sementara di BSD/macOS menggunakan kqueue().
  • Windows sudah menggunakan WaitForSingleObject, sehingga tidak ada perubahan di sana, tetapi pada sistem POSIX, context switching yang tidak perlu dihilangkan dan penggunaan CPU mendekati '0'.

Ringkasan detail:
1. Masalah yang bertahan selama 15 tahun: Busy-loop polling
Sejak parameter timeout ditambahkan ke subprocess.Popen.wait() pada Python 3.3, library standar Python dan library psutil yang banyak digunakan telah memakai cara yang tidak efisien untuk menunggu proses selesai.

Logika lama sederhana, tetapi tidak efisien:

  1. Periksa status proses dengan waitpid(WNOHANG) (non-blocking)
  2. Jika belum selesai, sleep() sebentar (dengan exponential backoff)
  3. Kembali ke langkah 1 dan ulangi
# Cara lama (kode konseptual)  
import time, os  
  
def wait_busy(pid, timeout):  
    delay = 0.0001  
    while True:  
        # Memeriksa apakah proses sudah berakhir (polling)  
        if os.waitpid(pid, os.WNOHANG) == (pid, status):  
            return status  
        time.sleep(delay)  
        delay = min(delay * 2, 0.040) # tingkatkan waktu tunggu hingga maksimum 40ms  
  

Pendekatan ini memiliki 3 kelemahan fatal berikut.

  • Wake-up CPU: Seberapa pun lama waktu tunggunya ditingkatkan, sistem tetap harus bangun secara berkala untuk memeriksa status, sehingga membuang siklus CPU dan mengonsumsi daya.
  • Latensi: Tak terhindarkan ada jeda waktu antara saat proses benar-benar berakhir dan saat sistem bangun dari sleep lalu mendeteksinya.
  • Skalabilitas: Dalam lingkungan server yang harus memantau ratusan hingga ribuan proses sekaligus, overhead ini meningkat tajam.

2. Solusi: Penantian berbasis event untuk sistem POSIX
Semua sistem POSIX menyediakan mekanisme (select, poll, epoll, kqueue) untuk mendeteksi perubahan status pada file descriptor. Baru-baru ini, Python dan psutil ditingkatkan untuk memanfaatkan mekanisme ini dalam mendeteksi PID proses.

  • Linux: Memanfaatkan system call pidfd_open() yang diperkenalkan pada kernel Linux 5.3 tahun 2019. Ini mengembalikan file descriptor yang menunjuk ke PID proses, lalu dapat didaftarkan ke poll() atau epoll() untuk memantau event berakhirnya proses. (Ditambahkan ke modul os sejak Python 3.9)
  • BSD / macOS: Menggunakan filter EVFILT_PROC pada system call kqueue() untuk memantau event proses secara efisien.
  • Windows: Sudah mendukung penantian berbasis event melalui API WaitForSingleObject, sehingga tidak ada perubahan.

3. Peningkatan performa dan hasil
Dengan perubahan ini, saat wait() dipanggil, dari sudut pandang kernel proses masuk ke status 'Interruptible sleep'. Artinya, proses dapat menunggu diam di ruang kernel tanpa mengonsumsi CPU sama sekali, lalu langsung bangun ketika sinyal berakhirnya proses terjadi.

Hasil benchmark dengan /usr/bin/time -v dan alat serupa menunjukkan bahwa dibanding cara lama, context switching yang tidak perlu berkurang drastis, dan kecepatan deteksi berakhirnya proses juga meningkat secara langsung. Pembaruan ini telah diterapkan pada library psutil dan inti CPython, sehingga ke depannya para pengembang Python bisa menikmati peningkatan performa ini tanpa perlu mengubah kode mereka sendiri.

Belum ada komentar.

Belum ada komentar.