The GIL and Workload Choice
A Python service has two hot paths:
- A route that computes SHA-256 hashes over large in-memory buffers in a tight Python loop.
- A route that fans out to five external HTTP APIs and aggregates the responses.
For each path, would you use threads, asyncio, or multiprocessing? Justify
each answer in terms of the GIL.
1. CPU-bound hashing → multiprocessing. The work is pure-Python CPU computation. The GIL allows only one thread to execute Python bytecode at a time, so adding threads gives no speedup — they just take turns. Multiple processes each have their own interpreter and GIL, so the hashing runs on multiple cores in true parallel. (Alternatively, a native extension that releases the GIL during the hash would also work.)
2. I/O-bound HTTP fan-out → asyncio (or threads).
Here the code spends almost all its time waiting on network responses,
not executing Python. During an await on a socket, the event loop is free
to start the other four requests, so all five are in flight concurrently on
a single thread. Threads would also work (a thread releases the GIL while
blocked on I/O), but asyncio scales to many concurrent waits more cheaply
than one thread per request.
Rule: processes for CPU-bound, async/threads for I/O-bound.