On Thu, Jun 18, 2020 at 9:34 AM Barry Scott
To make the code avoid COW you would need to be able to make sure that all code memory blocks are not mixed in with PyObject memory blocks.
Then the ref count dance will have trigger COW for the code.
indeed. cPython already has its own memory allocator, yes? how hard would it be to allocate all "immortal" objects in the same region in memory, and regular objects in another? Presumably that would only be a cost at allocation time, and probably not a large one. So the trick is to determine what objects are immortal. And Jonathan has a good point: though Python is perfectly capable of creating and destroying code objects (functions, classes, etc, in practice, most do survive the length of the program, so there would be little memory wasted in most cases by making them immortal. And maybe the interpreter could be smart about guessing which are most likely to be mortal. Finally, if this really does make a difference, then we could add ways for the programmer to mark certain code objects as mortal or immortal as need be. Finally -- and I'm way out of my depth here -- does this mean there is potential to significantly improve the performance of multiprocessing? Which would be really, really, great, as the GIL has proven an intractable barrier to certain kinds of multi-threading. -CHB
Barry
I hope this helps.
Jonathan
APPENDICES ===========
SOME IMPLEMENTATION DETAILS AND COMMENTS Because fn.__code__ must not return a permanent object, some sort of opaque proxy would be required. Because Python programs rarely inspect fn.__code__, in practice the cost of this additional indirection is likely to be small.
As things are, the time spent changing the refcount of fn.__code__ is probably insignificant. The benefit is that permanent code objects are made immutable, and so can be stored safely in read-only memory (that can be shared across all processes and users). Code objects are special, in that they are only rarely looked at directly. Their main purpose is to be used by the interpreter.
Python allows the user to replace fn.__code__ by a different code object. This is a rarely done dirty trick. The transient / permanent nature of fn.__code__ could be stored as a hidden field on the fn object. This would reduce the cost of the if ... else ... branching, as it amounts to caching the transient / permanent nature of fn.__code__.
FORK AND COPY ON WRITE On Unix, the fork system call causes a process to make a child of itself. The parent and child share memory. To avoid confusion and errors, when either asks the system to write to shared memory, the system ensures that both parent and child have their own copy (of the page of memory that is being written to). This is an expensive operation. See: https://en.wikipedia.org/wiki/Copy-on-write
INTERPRETER SESSION
>>> from sys import getrefcount as grc
# Identical functions with different code objects. >>> def f1(obj): return grc(obj) >>> def f2(obj): return grc(obj) >>> f1.__code__ is f2.__code__ False
# Initial values. >>> grc(f1.__code__), grc(f2.__code__) (2, 2)
# Calling f1 increases the refcount of f1.__code__. >>> f1(f1), f1(f2), f2(f1), f2(f2) (6, 4, 4, 6)
# If fn is a generator function, then x = fn() will increase the # refcount of fn.__code__. >>> def f1(): yield True >>> grc(f1.__code__) 2
# Let's create and store 10 generators. >>> iterables = [f1() for i in range(10)] >>> grc(f1.__code__) 22
# Let's get one item from each. >>> [next(i) for i in iterables] [True, True, True, True, True, True, True, True, True, True] >>> grc(f1.__code__) 22
# Let's exhaust all the iterables. This reduces the refcount. >>> [next(i, False) for i in iterables] [False, False, False, False, False, False, False, False, False, False] >>> grc(f1.__code__) 12
# Nearly done. Now let go of the iterables. >>> del iterables >>> grc(f1.__code__) 2
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/SFCJS2... Code of Conduct: http://python.org/psf/codeofconduct/
_______________________________________________ Python-ideas mailing list -- python-ideas@python.org To unsubscribe send an email to python-ideas-leave@python.org https://mail.python.org/mailman3/lists/python-ideas.python.org/ Message archived at https://mail.python.org/archives/list/python-ideas@python.org/message/TZO7AG... Code of Conduct: http://python.org/psf/codeofconduct/
-- Christopher Barker, PhD Python Language Consulting - Teaching - Scientific Software Development - Desktop GUI and Web Development - wxPython, numpy, scipy, Cython