Hi,

I'm generally in favour of PEP 554, but I don't think it is ready to be accepted in its current form.

My main objection is that without per-subinterpeter GILs (SILs?) PEP 554 provides no value over threading or multi-processing. Multi-processing provides true parallelism and threads provide shared memory concurrency.

If per-subinterpeter GILs are possible then, and only then, sub-interpreters will provide true parallelism and (limited) shared memory concurrency.

The problem is that we don't know whether we can implement per-subinterpeter GILs without too large a negative performance impact.
I think we can, but we can't say so for certain.

So, IMO, we should not accept PEP 554 until we know for sure that per-subinterpeter GILs can be implemented efficiently.



Detailed critique
-----------------

I don't see how `list_all()` can be both safe and accurate. The Java equivalent makes no guarantees of accuracy. Attempting to lock the list is likely to lead to deadlock and not locking it will lead to races; potentially dangerous ones.
I think it would be best to drop this.

`list_all_channels()`. See `list_all()` above.

`.destroy()` is either misleading or unsafe.
What does this do?

>>> is.destroy()
>>> is.run()

If `run()` raises an exception then the interpreter must exist. Rename to `close()` perhaps?

`Channel.interpreters` see `list_all()` and `list_all_channels()` above.

How does `is_shareable()` work? Are you proposing some mechanism to transfer an object from one sub-interpreter to another? How would that work? If objects are not shared but serialized, why not use marshal or pickle instead of inventing a third serialization protocol?

It would be clearer if channels only dealt with simple, contiguous binary data. As it stands the PEP doesn't state what form the received object will take. Once channels supporting the transfer of bytes objects work, then it is simple to pass more complex objects using pickle or marshal.

Channels need a more detailed description of their lifespan. Ideally a state machine.
For example:
How does an interpreter detach from the receiving end of a channel that is never empty? What happens if an interpreter deletes the last reference to a non-empty channel? On the receiving end, or on the sending end?

Isn't the lack of buffering in channels a recipe for deadlocks?

What is the mechanism for reliably copying exceptions from one sub-interpreter to another in the `run()` method? If `run()` can raise an exception, why not let it return values?


Cheers,
Mark.
_______________________________________________
Python-Dev mailing list -- python-dev@python.org
To unsubscribe send an email to python-dev-le...@python.org
https://mail.python.org/mailman3/lists/python-dev.python.org/
Message archived at 
https://mail.python.org/archives/list/python-dev@python.org/message/ZSE2G37E24YYLNMQKOQSBM46F7KLAOZF/
Code of Conduct: http://python.org/psf/codeofconduct/

Reply via email to