Membuka Pikiran
Bagaimana Anda sampai pada kesimpulan bahwa beberapa bagian sistem akan lebih baik dalam bahasa lain? Apakah Anda mengalami masalah kinerja? Seberapa parah masalah itu? Jika itu bisa lebih cepat, apakah penting bahwa itu lebih cepat?
Sinkronisasi Satu-utas
Ada beberapa pertanyaan dan sumber daya web lain yang sudah berurusan dengan perbedaan, pro, dan kontra dari asynchrony single-thread vs multi-thread concurrency. Sangat menarik untuk membaca tentang bagaimana model asinkron single-thread Node.js tampil ketika I / O adalah hambatan utama, dan ada banyak permintaan yang dilayani sekaligus.
Twisted, Tornado, dan model asinkron lainnya memanfaatkan sekali utas. Karena banyak pemrograman web memiliki banyak I / O (jaringan, database, dll.), Waktu yang dihabiskan untuk menunggu panggilan jarak jauh bertambah secara signifikan. Itulah waktu yang dapat dihabiskan untuk melakukan hal-hal lain — seperti memulai panggilan basis data lain, merender halaman, dan menghasilkan data. Pemanfaatan single-thread itu sangat tinggi.
Salah satu manfaat terbesar dari asynchrony single-thread adalah menggunakan lebih sedikit memori. Dalam eksekusi multi-utas, setiap utas membutuhkan sejumlah memori yang dicadangkan. Saat jumlah utas meningkat, demikian juga jumlah memori yang diperlukan hanya agar utas ada. Karena memori terbatas, itu berarti ada batasan pada jumlah utas yang dapat dibuat pada satu waktu.
Contoh
Dalam kasus server web, berpura-pura setiap permintaan diberikan utasnya sendiri. Katakanlah 1MB memori diperlukan untuk setiap utas, dan server web memiliki 2GB RAM. Server web ini akan mampu memproses (kira-kira) 2000 permintaan kapan saja sebelum tidak ada cukup memori untuk diproses lagi.
Jika beban Anda secara signifikan lebih tinggi dari ini, permintaan akan memakan waktu yang sangat lama (ketika menunggu permintaan yang lebih lama selesai), atau Anda harus membuang lebih banyak server ke dalam kluster untuk memperluas jumlah permintaan bersamaan yang mungkin terjadi .
Multi-thread Concurrency
Konkurensi multi-utas alih-alih bergantung pada menjalankan beberapa tugas pada saat yang sama. Itu berarti bahwa jika utas diblokir menunggu panggilan database kembali, permintaan lain dapat diproses pada saat yang sama. Utilisasi thread lebih rendah, tetapi jumlah thread yang dieksekusi jauh lebih besar.
Kode multi-utas juga jauh lebih sulit untuk dipikirkan. Ada masalah dengan penguncian, sinkronisasi, dan masalah concurrency menyenangkan lainnya. Single-thread asynchrony tidak mengalami masalah yang sama.
Namun kode multi-thread jauh lebih berkinerja untuk tugas-tugas intensif CPU . Jika tidak ada peluang bagi utas untuk "menghasilkan" —seperti panggilan jaringan yang biasanya akan diblokir — model utas tunggal tidak akan memiliki konkurensi apa pun.
Keduanya hidup berdampingan
Tentu saja ada tumpang tindih antara keduanya; mereka tidak saling eksklusif. Misalnya, kode multi-utas dapat ditulis dengan cara non-pemblokiran, untuk memanfaatkan setiap utas dengan lebih baik.
Garis bawah
Ada banyak masalah lain yang perlu dipertimbangkan, tetapi saya suka memikirkan keduanya seperti ini:
- Jika program Anda terikat I / O , maka asynchrony single-thread mungkin akan bekerja dengan baik.
- Jika program Anda terikat CPU , maka sistem multi-thread mungkin akan lebih baik.
Dalam kasus khusus Anda, Anda perlu menentukan jenis pekerjaan asinkron yang sedang diselesaikan, dan seberapa sering tugas-tugas itu muncul.
- Apakah itu terjadi pada setiap permintaan? Jika demikian, memori mungkin akan menjadi masalah karena jumlah permintaan meningkat.
- Apakah tugas ini dipesan? Jika demikian, Anda harus mempertimbangkan sinkronisasi jika menggunakan banyak utas.
- Apakah tugas-tugas ini intensif CPU? Jika demikian, apakah satu utas dapat mengimbangi beban?
Tidak ada jawaban sederhana. Anda harus mempertimbangkan apa yang Anda gunakan, dan desain yang sesuai. Terkadang model single-thread asynchronous lebih baik. Di lain waktu, menggunakan sejumlah utas untuk mencapai pemrosesan paralel masif diperlukan.
Pertimbangan Lainnya
Ada masalah lain yang perlu Anda pertimbangkan juga, bukan hanya model konkurensi yang Anda pilih. Apakah Anda tahu Erlang atau Clojure? Apakah Anda pikir Anda akan mampu menulis kode multi-thread yang aman dalam salah satu bahasa ini sehingga Anda meningkatkan kinerja aplikasi Anda? Apakah perlu waktu lama untuk mempercepat salah satu bahasa ini, dan apakah bahasa yang Anda pelajari akan menguntungkan Anda di masa depan?
Bagaimana dengan kesulitan yang terkait dengan komunikasi antara kedua sistem ini? Apakah akan terlalu rumit mempertahankan dua sistem terpisah secara paralel? Bagaimana sistem Erlang akan menerima tugas dari Django? Bagaimana Erlang akan mengkomunikasikan hasil itu kembali ke Django? Apakah kinerja cukup signifikan sebagai masalah sehingga kompleksitas yang ditambahkan sepadan?
Pikiran terakhir
Saya selalu menemukan Django cukup cepat, dan digunakan oleh beberapa situs yang sangat diperdagangkan. Ada beberapa optimisasi kinerja yang dapat Anda lakukan untuk meningkatkan jumlah permintaan dan waktu respons bersamaan. Memang, saya belum melakukan apa-apa dengan Celery sejauh ini, jadi optimisasi kinerja yang biasa mungkin tidak akan menyelesaikan masalah apa pun yang mungkin Anda alami dengan tugas-tugas tidak sinkron ini.
Tentu saja, selalu ada saran untuk melemparkan lebih banyak perangkat keras pada masalahnya. Apakah biaya penyediaan server baru lebih murah daripada biaya pengembangan dan pemeliharaan subsistem yang sama sekali baru?
Saya sudah mengajukan terlalu banyak pertanyaan pada saat ini, tapi itu maksud saya. Jawabannya tidak akan mudah tanpa analisis dan perincian lebih lanjut. Mampu menganalisis masalah datang ke mengetahui pertanyaan untuk diajukan, meskipun ... jadi mudah-mudahan saya telah membantu di depan
Perasaan saya mengatakan bahwa menulis ulang dalam bahasa lain tidak perlu. Kompleksitas dan biaya mungkin akan terlalu besar.
Edit
Tanggapan untuk Tindak Lanjut
Tindak lanjut Anda menyajikan beberapa kasus penggunaan yang sangat menarik.
1. Django bekerja di luar permintaan HTTP
Contoh pertama Anda melibatkan membaca tag NFC, lalu menanyakan database. Saya tidak berpikir bahwa menulis bagian ini dalam bahasa lain akan berguna bagi Anda, hanya karena permintaan basis data atau server LDAP akan terikat oleh jaringan I / O (dan berpotensi kinerja database). Di sisi lain, jumlah permintaan bersamaan akan terikat oleh server itu sendiri, karena setiap perintah manajemen akan dijalankan sebagai prosesnya sendiri. Akan ada waktu penyiapan dan penghancuran yang mempengaruhi kinerja, karena Anda tidak mengirim pesan ke proses yang sudah berjalan. Anda akan, bagaimanapun, dapat mengirim beberapa permintaan secara bersamaan, karena masing-masing akan menjadi proses yang terisolasi.
Untuk kasus ini, saya melihat dua jalan yang bisa Anda selidiki:
- Pastikan bahwa database Anda mampu menangani beberapa pertanyaan sekaligus dengan penyatuan koneksi. (Oracle, misalnya, mengharuskan Anda mengkonfigurasi Django yang sesuai
'OPTIONS': {'threaded':True}
.) Mungkin ada opsi konfigurasi serupa di tingkat basis data atau tingkat Django yang dapat Anda atur untuk basis data Anda sendiri. Tidak peduli bahasa apa yang Anda gunakan untuk query database, Anda harus menunggu data ini kembali sebelum Anda dapat menyalakan LED. Kinerja kode kueri dapat membuat perbedaan, dan Django ORM tidak secepat kilat ( tapi , biasanya cukup cepat).
- Minimalkan waktu setup / teardown. Memiliki proses yang terus berjalan, dan mengirim pesan ke sana. (Koreksi saya jika saya salah, tetapi inilah yang menjadi fokus pertanyaan asli Anda.) Apakah proses ini ditulis dalam Python / Django atau bahasa / kerangka kerja lain dibahas di atas. Saya tidak suka gagasan sering menggunakan perintah manajemen. Mungkinkah ada sepotong kecil kode yang berjalan terus-menerus, yang mendorong pesan dari pembaca NFC ke antrian pesan, yang kemudian dibaca oleh Celery dan diteruskan ke Django? Setup dan teardown dari program kecil, bahkan jika itu ditulis dalam Python (tetapi bukan Django!), Harus lebih baik daripada memulai dan menghentikan program Django (dengan semua subsistemnya).
Saya tidak yakin server web apa yang Anda gunakan untuk Django. mod_wsgi
untuk Apache memungkinkan Anda mengonfigurasi jumlah proses dan utas dalam proses yang diminta layanan. Pastikan untuk mengubah konfigurasi server web Anda yang relevan untuk mengoptimalkan jumlah permintaan yang dapat diperbaiki.
2. "Pesan-lewat" dengan sinyal Django
Kasing kedua Anda juga cukup menarik; Saya tidak yakin apakah saya punya jawaban untuk itu. Jika Anda menghapus instance model, dan ingin mengoperasinya nanti, mungkin saja membuat serial JSON.dumps
dan kemudian membatalkan deserialisasi JSON.loads
. Tidak mungkin untuk membuat kembali sepenuhnya objek grafik nanti (menanyakan model terkait), karena bidang terkait malas dimuat dari database, dan tautan itu tidak lagi ada.
Pilihan lain adalah entah bagaimana menandai objek untuk dihapus, dan hanya menghapusnya di akhir siklus permintaan / respons (setelah semua sinyal diservis). Mungkin memerlukan sinyal khusus untuk menerapkan ini, daripada mengandalkan post_delete
.