Author: Antonio Cuni <anto.c...@gmail.com>
Branch: extradoc
Changeset: r5897:cd51a2e3fc4d
Date: 2018-09-04 12:23 +0200
http://bitbucket.org/pypy/extradoc/changeset/cd51a2e3fc4d/

Log:    write this section; I am not very satisfied about it, but better to
        write down some words that stare at the blank page; feel free to
        improve :)

diff --git a/blog/draft/2018-09-cpyext/cpyext.rst 
b/blog/draft/2018-09-cpyext/cpyext.rst
--- a/blog/draft/2018-09-cpyext/cpyext.rst
+++ b/blog/draft/2018-09-cpyext/cpyext.rst
@@ -181,4 +181,43 @@
 Maintaining the link between ``W_Root`` and ``PyObject *``
 -----------------------------------------------------------
 
-WRITE ME
+So, we need a way to convert between ``W_Root`` and ``PyObject *`` and
+vice-versa; also, we need to to ensure that the lifetime of the two entities
+are in sync. In particular:
+
+  1. as long as the ``W_Root`` is kept alive by the GC, we want the
+     ``PyObject *`` to live even if its refcount drops to 0;
+
+  2. as long as the ``PyObject *`` has a refcount greater than 0, we want to
+     make sure that the GC does not collect the ``W_Root``.
+
+The ``PyObject *`` ==> ``W_Root`` link is maintained by the special field
+_`ob_pypy_link` which is added to all ``PyObject *``: on a 64 bit machine this
+means that all ``PyObject *`` have 8 bytes of overhead, but then the
+conversion is very quick, just reading the field.
+
+For the other direction, we generally don't want to do the same: the
+assumption is that the vast majority of ``W_Root`` objects will never be
+passed to C, and adding an overhead of 8 bytes to all of them is a
+waste. Instead, in the general case the link is maintained by using a
+dictionary, where ``W_Root`` are the keys and ``PyObject *`` the values.
+
+However, for a _`few selected` ``W_Root`` subclasses we **do** maintain a
+direct link using the special ``_cpy_ref`` field to improve performance. In
+particular, we use it for ``W_TypeObject`` (which is big anyway, so a 8 bytes
+overhead is negligible) and ``W_NoneObject``: ``None`` is passed around very
+often, so we want to ensure that the conversion to ``PyObject *`` is very
+fast. Moreover it's a singleton, so the 8 bytes overhead is negligible as
+well.
+
+This means that in theory, passing an arbitrary Python object to C is
+potentially costly, because it involves doing a dictionary lookup.  I assume
+that this cost will eventually show up in the profiler: however, at the time
+of writing there are other parts of cpyext which are even more costly (as we
+will show later), so the cost of the dict lookup is never evident in the
+profiler.
+
+
+.. _`ob_pypy_link`: 
https://bitbucket.org/pypy/pypy/src/942ad6c1866e30d8094d1dae56a9b8f492554201/pypy/module/cpyext/parse/cpyext_object.h#lines-5
+
+.. _`few selected`: 
https://bitbucket.org/pypy/pypy/src/942ad6c1866e30d8094d1dae56a9b8f492554201/pypy/module/cpyext/pyobject.py#lines-66
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to