Python 3.x: Threading vs Multiprocessing vs Asyncio

July 29, 2019

GIL - Global interpreter lock

  • To make thread-safe API call and reference counting (memory management), GIL is introduced (in 1992).
  • Since there is only 1 GIL shared by all threads, thus only 1 thread gets to execute at any one time (no parallel execution with only single core is utilized)
  • GIL is dopped occasionally when not needed: sleep, read/write to file/socket
  • Good for IO bound task, really bad for CPU bound task
  • Only CPython (default python interpreters) implement GIL; jython, ironpython and pypy does not implement GIL, but they use a different garbage collection system (pure gc - periodic check reference count)

Threading

  • Thread: shared memory (easier communication between threads)
  • Need a lock for non atomic function like increment counter
  • To avoid lock, use thread-safe atomic message queue
  • Utilize single core: concurrent execution, subject to GIL
  • Task switching handled by OS
  • Very hard to write and maintain correct code

Multiprocessing

  • Utilize multiple CPU cores: good for CPU bound task, bypass GIL limitation, parallel execution
  • Process: separate and larger memory foodprint
  • IPC more complicated and overheads than threads
  • Spawn process is slower than launch thread
  • You can kill a process (but not a thread)

Asyncio

  • Faster than threads
  • Replace callbacks with await
  • Good for IO bound
  • Need to make use of aiohttp for network request; network call using requests or using python libraries for google REST API (which yet to support asyncio) is still blocking, or you need to write a async wrapper around these code. The sames goes for other IO function where you requires the async version.
  • Harder to write than threading, but easier to get it right than threading.
  • Utilize single core only: concurrent but not parallel execution
  • Task switching handled by you (as appose to Thread which is handled by OS) when you call sleep or await, and the cost of task switching is very low (with no lock required).
  • Mix asyncio with multiprocessing to untilize multi core: aiomultiprocess

References:

This work is licensed under a
Creative Commons Attribution-NonCommercial 4.0 International License.