If anyone is wondering why the threaded implementation was slower
> pool = ThreadPool(40)
> pool = ThreadPool(40)
All but one of the runnable threads are waiting on the GIL. The "not runnable" threads are waiting on some lock or a blocking system call.
I get a lot of people have gotten mileage out of event loop scaling over the last 10-15 years (that's the trick of nginx, node.js, etc, right?), but even raspberry pis are quad core?
If you have a lot of parallel computation, Python may not be a great choice. However, if you're managing a lot of IO with not much computation, Python is perfectly reasonable.