The same holds for various CPU intensive standard library functions implemented in C.
The GIL issue is real, but posts like this one confused me for years. Please, don’t exaggerate GIL issues.
That caveat is somewhat true for all programming abstractions, but well-designed interfaces make the more efficient techniques more obvious and beautiful, while the inefficient or risky techniques are made esoteric and ugly.
In general, the "just rewrite the slow parts in C!" motto is terrible advice because it's unlikely that it will actually make your code appreciably slower, and if it does, it's very likely to be defeated unexpectedly as soon as requirements change. Using FFI to make things faster can work, but only if you've really considered your problem and you're quite sure you can safely predict relevant changes to requirements.
There are plenty of pitfalls in leaky abstractions. Establishing that fast numeric calculations only work with specific numeric types seems to help.
One thing you seem to be encountering, that I've seen a few times, is that people don't realize NumPy and core Python are almost orthoganal. The best practices for each are nearly opposite. I try to make it clear when I'm switching from one to the other by explaining the performance optimization (broadly) in comments.
Regardless, any function that receives a ``list`` of ints will need to convert to an ndarray if it wants NumPy speed. If the function interface is modified later, I think it's fair to expect the editor to understand why.
Sure, but this is a _massive_ pitfall. It's an optimization that can trivially make your code slower than the naive Python implementation, all due to a leaky abstraction.
> Regardless, any function that receives a ``list`` of ints will need to convert to an ndarray if it wants NumPy speed. If the function interface is modified later, I think it's fair to expect the editor to understand why.
Yeah, that was a toy example. In practice, the scenario was similar except the function called to a third party library that used Numpy under the hood. We introduced a ton of complexity to use this third party library on the grounds that "it will make things fast" instead of the naive list implementation, and the very next sprint we needed to update it such that it became 10X slower than the naive Python implementation.
That's the starkest example, but there have been others and there would have been many more if we didn't have the stark example to point to.
The current slogan is "just use Python; you can always make things fast with Numpy/native code!", but it should be "use Python if you have a deep understanding of how Numpy (or whatever native library you're using) makes things fast such that you can count on that invariant to hold even as your requirements change" or some such.
It seems reasonable that different parts of the code are appropriate for modification by engineers of differing skills.
IIRC, I've only ever seen "unawaited coroutine found" (or similar) errors; I've never seen anything that points to a specific unawaited coroutine. In either case, a bug in prod is still many times worse than compile time type error.
> you can enable debug on the event loop and have it print out every time a coroutine takes longer than a configurable amount of time
I don't run my production servers in debug mode, and even when I do manage to find the problem, I have limited options for solving it. Usually it amounts to refactoring out the offending code into a separate process or service.
An extreme counterpoint is a language like Go which
1) Is roughly 100X faster in single-threaded, CPU-bound execution anyway
2) Allows for additional optimizations that simply aren't possible in Python (mostly involving reduced allocations and improved cache coherence)
3) Has a runtime that balances CPU load across all available cores
This isn't a "shit on Python" post; only that concurrency really isn't Python's strong suit (yet).
And yet we see the same incorrect information trotted out over and over again.
- it's easy to learn - we've go numpy
If I were to pick a language to build significant infrastructure with, I wouldn't choose python.
Because it's a distributed environment probably is exactly why. Python has (arguably) great concurrency support apart from Multi-threading.
https://www.youtube.com/watch?v=MCs5OvhV9S4
So if you need concurrency in the context of a single thread, then Python's GIL is a non-starter. But a distributed environment is not likely one of those.
Edit: I should amend concurrency in a single thread to: concurrency in a single thread that is compute gated...since coroutines can give you pseudo concurrency in a single thread provided you're workload has blocking steps like IO or TCP calls.