Hướng dẫn python asyncio, multiprocessing

Introduction

Nếu bạn đã làm các dự án về Python, bạn sẽ gặp trường hợp code của mình chạy quá chậm. Có nhiều cách để cải thiện việc này. Ở đây, mình sẽ hướng dẫn cải thiện hiệu năng thông qua lập trình song song.

Hướng dẫn python asyncio, multiprocessing
.

Asynchronous Programming

Từ Python 3.4, chúng ta có 1 module mới với tên là asyncio.

asyncio sử dụng syntax async/await giống với Javascript ES6.

asyncio thường được sử dụng với hệ thống IO-bound and high-level structured network code.

asyncio cung cấp APIs dùng để:

  • Run Python coroutines concurrently
  • Control over their execution
  • Control subprocesses
  • Synchronize concurrent code
  • Distribute tasks via queues ...

Example:

>>> import asyncio
>>> async def coroutine_1():
...     print('coroutine_1 yielding control. Going to be blocked for 10 seconds')
...     await asyncio.sleep(10)
... 
>>> async def coroutine_2():
...     print('coroutine_2 yielding control. Going to be blocked for 5 seconds')
...     await asyncio.sleep(5)
...
>>> loop = asyncio.get_event_loop()
>>>
>>> loop.run_until_complete(asyncio.gather(coroutine_1(), coroutine_2()))
coroutine_2 yielding control. Going to be blocked for 5 seconds
coroutine_1 yielding control. Going to be blocked for 10 seconds
[None, None]

Ưu điểm khi sử dụng asyncio là nó phù hợp với hệ thống IO-bound và high-level structured network code.

Nhược điểm là nếu hệ thống của bạn dạng CPU-bound thì chẹp.. consider sử dụng multiprocessing/multithreading thay thế. Ngoài ra, những hệ thống Python cũ hơn 3.4 thì Say good bye và không hẹn gặp lại.

Using Worker: JobQueue và Pubsub

Một giải pháp nữa nó lại không quá liên quan tới Python. Nó liên quan tới kiến trúc hệ thống nhiều hơn. Với những hệ thống Python version đã cũ. Nếu việc upgrade Python version nó không khả thi, bạn có thể consider đến giải pháp này.

Nếu các logic của bạn phức tạp và xử lý rất nhiều dữ liệu thì tạo dựng một vài con worker sẽ không phải ý tồi.

Thường các con worker mình sẽ sử dụng 2 cơ chế chính là:

  • JobQueue
  • PubSub

Redis đều hỗ trợ rất tốt 2 cơ chế này.

Example Job Queue:

# worker.py
from mymodule import count_words_at_url
from redis import Redis
from rq import Queue


q = Queue(connection=Redis())
job = q.enqueue(count_words_at_url, 'http://dantri.com')



# mymodule.py
import requests

def count_words_at_url(url):
    resp = requests.get(url)
    print( len(resp.text.split()))

Example Pubsub bạn có thể tham khảo tại đây:https://viblo.asia/p/gioi-thieu-ve-pubsub-va-su-dung-python-va-redis-demo-pubsub-V3m5WbywlO7

Ưu điểm khi sử dụng giải pháp này là mình có thể tận dụng các hệ thống Python đã rất cũ nhưng muốn nó vẫn chạy ngon.

Nhược điểm là vì là giải pháp này mang tính hệ thống nhiều nên cần phải cân nhắc rất kỹ.

Conclusion

Parallel programming là một giải pháp để tăng performance cho các project Python. Và tất nhiên tùy thuộc vào bài toán của mình để áp dụng giải pháp nào tốt nhất.