<disclaimer>
I’m author of “competing” (not really) PEPs: 683 (immortal objects) and 684 (per-interpreter GIL).
To be clear, I do not consider this proposal to be mutually exclusive with a per-interpreter GIL (nor with multiple isolated interpreters generally). I consider them to be completely compatible, both conceptually and in the implementation. Fundamentally, they focus on different concurrency models. Furthermore, code changes made for the one will almost always benefit the other.
</disclaimer>
tl;dr I’m really excited by this proposal but have significant concerns, which I genuinely hope the PEP can address.
Overall, I’m quite happy to see this PEP and would love to see CPython without the GIL. Misconceptions about the GIL have been a consistent obstacle to Python adoption in the industry for a long time. (FWIW, that was the main motivator, in 2014, to start my own project to improve Python’s multi-core story.) So any successful approach to doing so is more than welcome!
That said, removing the GIL isn’t trivial and will necessarily come with tradeoffs. I’m seriously concerned by the likely negative impacts (which the PEP needs to address clearly, if not already). Fundamentally, removing the GIL would increase the maintenance burden on maintainers of both CPython and extension modules, as well as likely lead to a (relatively large?) regression to single-threaded performance. To be successful, the PEP needs to be clear about how these are either mitigated or compensated by the benefits, sufficient to show that it’s clearly worth doing.
Specifically, the proposed solution negatively impacts:
- CPython maintainers (mostly volunteers)
- increased complexity in runtime code
- must now think about thread-safety everywhere (see the “Thread-Safety” section below)
- some code will be more fragile (incl. in hard-to-debug ways, because threads)
- extra CI resources needed (e.g. buildbots)
- reflexive flinching due to the experience of Py3k (e.g. 2-to-3 migration, maintaining 2 parallel release branches)
- extension module maintainers (mostly community volunteers)
- may effectively double a project’s support/CI matrix
- must now think about thread-safety (see the “Thread-Safety” section below)
- may have to maintain dual implementations of some code (w/ GIL and w/o GIL)
- projects may not have time to do the work (see the “Extension Maintainers” section below)
- users
- worse performance of single-threaded execution (see the “Performance” section below)
- many more users actually paying this than will benefit from no GIL
- now users will complain about performance instead of about the GIL
- if any, changes in the semantics of Python code (e.g. how locks behave)
- many will suddenly realize that programming with threads isn’t easy/fun, doesn’t actually solve any of their problems, and doesn’t make their code much faster (if at all)
- worse performance of single-threaded execution (see the “Performance” section below)
Additionally, the PEP should be very clear (and specific) about:
- how many extensions will be affected?
- how much work to fix each?
- how many unforeseen gaps in CPython’s test coverage?
- how do the benefits of removing the GIL outweigh the new costs?
Other questions:
- how much work to update the no-gil branch to the main (i.e. 3.12) branch? (a lot has changed since 3.9 in the eval loop and continues to change)
- how does the proposal affect other Python implementations (will they be expected to support multi-core threads)?
- will there be a new modulespec slot (see PEP 489) to indicate support for no-gil?
- how will pip be affected?
In summary, there are some serious obstacles to the PEP and a number of unclear points and unanswered questions, but I’m still cheering you on!
==========
Feedback on specific topics:
expand
Thread-Safety
Programming with threads has never been great. Beyond basic usage (and even then), it’s easy to get threads wrong and hard to feel confident that you’ve gotten it right. When things go wrong, they are a genuine pain to diagnose and debug (and even reproduce). I argue that threads are not a human-friendly concurrency model. That said, they are certainly ubiquitous in software and sometimes even the right tool for the job. This PEP needs to be clear about this penalty and any mitigations.
The biggest concerns (which impact maintenance costs for a project):
- few extensions give a second thought to thread-safety, because of the GIL
- now thread-safety would be a cross-cutting concern in all code at all times
- most maintainers won’t have much experience with thread-safety, where even experienced users get tripped up occasionally
- it’s easy to miss something when thread-safety is involved, and not even catch it right away (e.g. before a release or a deployment to production)
- thread-safe code is often not the same as regular code, so there may be surge (and cascade) of
#ifdefs
All the above also applies to CPython’s code. Furthermore, extra complexity has a real cost on CPython maintainability:
- in a number of places (e.g. dict), existing code must become more complex to achieve thread-safety (without the GIL) in an efficient way
- this adds cost to working on that code
- that either requires extra volunteer time or deters contributors from participating
Performance
- how big a regression without mitigations?
- what are the specific mitigations?
- how much do they reduce the regression?
- how many are worth doing anyway? (they may end up being done independently and not really be considered mitigations)
- how much has the “faster-cpython” work impacted
FWIW, Fedora recently had a long discussion (several actually) about making -fno-omit-frame-pointer default for C compilation: https://pagure.io/fesco/issue/2817. A key point was about how everyone would pay for the performance regression will only a small subset would benefit. Overall, that discussion has a number of parallels with the concerns of this PEP.
Extension Maintainers
Even if extension module maintainers have the option to not support a no-gil mode, users will ask for it. This can put a lot of pressure on already over-extended volunteers to work on a feature in which they don’t necessarily have much interest, nor time/resources to something about it. I’ve faced this problem with my own project, as discussed in PEP 554 and PEP 684.
So the PEP needs to be extra clear on how the burden (and pressure) on these maintainers will be mitigated.