Saya baru mengenal gevents dan greenlets. Saya menemukan beberapa dokumentasi yang bagus tentang cara bekerja dengan mereka, tetapi tidak ada yang memberi saya pembenaran tentang bagaimana dan kapan saya harus menggunakan greenlets!
- Apa yang benar-benar mereka kuasai?
- Apakah ide yang baik untuk menggunakannya di server proxy atau tidak?
- Kenapa tidak utas?
Apa yang saya tidak yakin tentang bagaimana mereka bisa memberikan kita konkurensi jika mereka pada dasarnya adalah co-rutinitas.
threading.Thread
sebenarnya adalah utas OS dengan semua konsekuensi. Jadi sebenarnya tidak sesederhana itu. Ngomong-ngomong, Jython tidak memiliki GIL AFAIK dan PyPy berusaha untuk menyingkirkannya juga.Jawaban:
Greenlets memberikan konkurensi tetapi tidak paralelisme. Concurrency adalah ketika kode dapat berjalan secara independen dari kode lain. Paralelisme adalah eksekusi kode konkuren secara bersamaan. Paralelisme sangat berguna ketika ada banyak pekerjaan yang harus dilakukan di userspace, dan itu biasanya hal-hal yang berat CPU. Concurrency berguna untuk memecahkan masalah, memungkinkan berbagai bagian dijadwalkan dan dikelola lebih mudah secara paralel.
Greenlets benar-benar bersinar dalam pemrograman jaringan di mana interaksi dengan satu soket dapat terjadi secara terpisah dari interaksi dengan soket lainnya. Ini adalah contoh klasik konkurensi. Karena setiap greenlet berjalan dalam konteksnya sendiri, Anda dapat terus menggunakan API sinkron tanpa threading. Ini bagus karena utas sangat mahal dalam hal memori virtual dan overhead kernel, sehingga konkurensi yang dapat Anda lakukan dengan utas jauh lebih sedikit. Selain itu, threading dengan Python lebih mahal dan lebih terbatas dari biasanya karena GIL. Alternatif untuk konkurensi biasanya proyek-proyek seperti Twisted, libevent, libuv, node.js dll, di mana semua kode Anda berbagi konteks eksekusi yang sama, dan mendaftarkan penangan acara.
Merupakan ide yang bagus untuk menggunakan greenlets (dengan dukungan jaringan yang sesuai seperti melalui gevent) untuk menulis proxy, karena penanganan permintaan Anda dapat dieksekusi secara independen dan harus ditulis seperti itu.
Greenlets memberikan konkurensi untuk alasan yang saya berikan sebelumnya. Konkurensi bukanlah paralelisme. Dengan menyembunyikan registrasi acara dan melakukan penjadwalan untuk Anda pada panggilan yang biasanya akan memblokir utas saat ini, proyek-proyek seperti gevent mengungkapkan konkurensi ini tanpa memerlukan perubahan ke API asinkron, dan dengan biaya yang jauh lebih murah untuk sistem Anda.
sumber
import hashlib def checksum_md5(filename): md5 = hashlib.md5() with open(filename,'rb') as f: for chunk in iter(lambda: f.read(8192), b''): md5.update(chunk) return md5.digest()
Mengambil jawaban @ Max dan menambahkan beberapa relevansi untuk penskalaan, Anda dapat melihat perbedaannya. Saya mencapai ini dengan mengubah URL yang akan diisi sebagai berikut:
Saya harus keluar versi multiproses karena jatuh sebelum saya punya 500; tetapi pada 10.000 iterasi:
Jadi Anda bisa melihat ada beberapa perbedaan yang signifikan dalam I / O menggunakan gevent
sumber
Mengoreksi jawaban @TemporalBeing di atas, greenlets tidak "lebih cepat" dari utas dan itu adalah teknik pemrograman yang salah untuk menelurkan 60000 utas untuk memecahkan masalah konkurensi, sekelompok kecil utas bukannya sesuai. Berikut ini adalah perbandingan yang lebih masuk akal (dari posting reddit saya dalam menanggapi orang-orang yang mengutip posting SO ini).
Berikut ini beberapa hasilnya:
kesalahpahaman yang dimiliki setiap orang tentang non-pemblokiran IO dengan Python adalah keyakinan bahwa juru bahasa Python dapat menangani pekerjaan mengambil hasil dari soket pada skala besar lebih cepat daripada koneksi jaringan itu sendiri dapat mengembalikan IO. Walaupun ini memang benar dalam beberapa kasus, itu tidak benar hampir sesering yang dipikirkan orang, karena interpreter Python benar-benar lambat. Dalam posting blog saya di sini , saya mengilustrasikan beberapa profil grafis yang menunjukkan bahwa untuk hal-hal yang sangat sederhana sekalipun, jika Anda berurusan dengan akses jaringan yang tajam dan cepat ke hal-hal seperti database atau server DNS, layanan tersebut dapat kembali jauh lebih cepat daripada kode Python dapat menangani ribuan koneksi tersebut.
sumber
Ini cukup menarik untuk dianalisis. Berikut ini adalah kode untuk membandingkan kinerja greenlets versus kumpulan multi-pemrosesan versus multi-threading:
berikut hasilnya:
Saya pikir Greenlet mengklaim bahwa itu tidak terikat oleh GIL tidak seperti perpustakaan multithreading. Selain itu, Greenlet doc mengatakan bahwa ini dimaksudkan untuk operasi jaringan. Untuk operasi jaringan yang intensif, penggantian ulir baik-baik saja dan Anda dapat melihat bahwa pendekatan multithreading cukup cepat. Juga selalu disukai menggunakan perpustakaan resmi python; Saya mencoba menginstal greenlet di windows dan mengalami masalah ketergantungan dll jadi saya menjalankan tes ini pada vm linux. Alway mencoba menulis kode dengan harapan dapat berjalan pada mesin apa pun.
sumber
getsockbyname
cache hasil pada level OS (setidaknya pada mesin saya itu hasilnya). Ketika dipanggil pada DNS yang sebelumnya tidak dikenal atau kedaluwarsa, itu akan benar-benar melakukan permintaan jaringan, yang mungkin memakan waktu. Ketika dipanggil pada nama host yang baru saja diselesaikan, itu akan mengembalikan jawabannya jauh lebih cepat. Akibatnya, metodologi pengukuran Anda cacat di sini. Ini menjelaskan hasil aneh Anda - gevent tidak bisa benar-benar jauh lebih buruk daripada multithreading - keduanya tidak-benar-paralel di tingkat VM.using_gevent() 421.442985535ms using_multiprocessing() 394.540071487ms using_multithreading() 402.48298645ms