Berawal dari server yang bengong karena proses for-loop yang berkepanjangan, saatnya untuk eksplorasi multi proses di Python. Artinya saat looping, proses akan dikerjakan oleh ‘worker’, sehingga loop bisa berlanjut ke baris berikutnya. Cocok untuk pemrosesan data per baris, seperti query lalu update satu-satu dengan proses panjang, atau proses unggah berkas per baris untuk satu persatu dimasukkan dalam database.
Ada beberapa alternatif:
- Thread + Queue
Ini standar bawaan Python. Langsung bisa pakai dengan kinerja yang mengagumkan. Kelemahannya adalah saat mengerjakan sesuatu tidak bisa ambil nilai kembalian hasil kerjaan tersebut (return value), kecuali lewat sub-classing dengan mengubah perilaku kelas utama dari Thread. - PythonRQ + Redis
Antriannya banyak pilihan dan bisa ambil nilai kembalian setelah menerapkan delay (1 detik). PythonRQ menerapkan fork untuk workernya (bukan thread), sehingga setiap proses berdiri sendiri. Tergantung sama Redis untuk menyimpan data antriannya. Cocok untuk distribusi kerjaan, tapi untuk kecepatan, kurang. - ThreadPool
Merupakan sub modul dari modul multiprocessing. Lebih cepat dari PythonRQ namun lebih lambat dari native Thread+Queue. Kelebihannya adalah bisa ambil nilai kembalian dengan mudah tanpa harus sub-classing.
Kode
Berikut contoh kode yang saya buat untuk pengujian:
import os import sys, time from Queue import Queue from threading import Thread from rq import Queue as rqueue from redis import Redis q = Queue() threads = 10 numrange = 1000 # fungsi yang akan dijalankan def deltrans(i): return "hello %s"%(i) #THREAD + QUEUE start = time.time() def dothing(q): while True: res = q.get() q.task_done return res for y in range(threads): worker = Thread(target=dothing, args =(q,)) worker.setDaemon(True) worker.start() for i in range(numrange): q.put(deltrans(i)) qtime = time.time()-start #PythonRQ astart = time.time() conn = Redis() rq = rqueue(connection = conn) from hworld import helloworld for i in range(numrange): hw = rq.enqueue(helloworld,i) print hw.result # ThreadPool btime = time.time()-astart from multiprocessing.pool import ThreadPool pool = ThreadPool(processes=threads) astart = time.time() for i in range(numrange): async_result = pool.apply_async(deltrans, (i,)) print async_result.get() ctime = time.time()-astart print "%s %s %s"%(qtime,btime,ctime)
Tambahan berkas hworld.py untuk PythonRQ:
def helloworld(i): return "hello %s"%(i)
Hasil
- Thread+ Queue: 0.0666551589966 (tanpa kembalian)
- PythonRQ: 0.510520935059 (tanpa kembalian, karena harus tunggu 1 detik untuk ambil kembalian)
- ThreadPool: 0.222325086594 (dengan kembalian)
Pendapat pribadi, jika tidak ingin kembalian, gunakan Thread+Queue. Jika ingin kembalian, gunakan ThreadPool. Jika ingin banyak manipulasi kembalian, gunakan PythonRQ.
Saya ingin bertanya. Error bagian;
1. from hworld import helloworld
ModuleNotFoundError: No module named ‘hworld’
2. Waktu install hworld anaconda promt
ERROR: Could not find a version that satisfies the requirement hworld (from versions: none)
ERROR: No matching distribution found for hworld
Mohon solusinya bagaimana.. Terimakasih
Itu file hworld.py-nya dibuat dulu di folder yang sama dengan file yang dibuat di file processnya. Kalau cobanya pakai notebook, tambahkan fungsi helloworld() sebelumnya
Untuk panduan Python Pemula, bisa dibaca dan diikuti secara urut di Ajar Kode – https://ajarkode.com