[pypy-commit] pypy default: cffi callbacks performance: rweaklist instead of rweakvaluedictionary

arigo noreply at buildbot.pypy.org
Fri Oct 9 17:56:21 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r80089:178e16fc3032
Date: 2015-10-09 15:20 +0200
http://bitbucket.org/pypy/pypy/changeset/178e16fc3032/

Log:	cffi callbacks performance: rweaklist instead of
	rweakvaluedictionary

diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -3,12 +3,12 @@
 """
 import sys, os
 
-from rpython.rlib import clibffi, rweakref, jit, jit_libffi
-from rpython.rlib.objectmodel import compute_unique_id, keepalive_until_here
+from rpython.rlib import clibffi, jit, jit_libffi
+from rpython.rlib.objectmodel import keepalive_until_here
 from rpython.rtyper.lltypesystem import lltype, rffi
 
 from pypy.interpreter.error import OperationError, oefmt
-from pypy.module._cffi_backend import cerrno, misc
+from pypy.module._cffi_backend import cerrno, misc, handle
 from pypy.module._cffi_backend.cdataobj import W_CData
 from pypy.module._cffi_backend.ctypefunc import SIZE_OF_FFI_ARG, W_CTypeFunc
 from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned
@@ -64,8 +64,14 @@
             convert_from_object_fficallback(fresult, self._closure.ll_error,
                                             w_error)
         #
-        self.unique_id = compute_unique_id(self)
-        global_callback_mapping.set(self.unique_id, self)
+        # We must setup the GIL here, in case the callback is invoked in
+        # some other non-Pythonic thread.  This is the same as cffi on
+        # CPython.
+        if space.config.translation.thread:
+            from pypy.module.thread.os_thread import setup_threads
+            setup_threads(space)
+        #
+        handle_index = handle.get_handles(space).reserve_next_handle_index()
         #
         cif_descr = self.getfunctype().cif_descr
         if not cif_descr:
@@ -74,7 +80,7 @@
                         "return type or with '...'", self.getfunctype().name)
         with self as ptr:
             closure_ptr = rffi.cast(clibffi.FFI_CLOSUREP, ptr)
-            unique_id = rffi.cast(rffi.VOIDP, self.unique_id)
+            unique_id = rffi.cast(rffi.VOIDP, handle_index)
             res = clibffi.c_ffi_prep_closure(closure_ptr, cif_descr.cif,
                                              invoke_callback,
                                              unique_id)
@@ -82,12 +88,8 @@
             raise OperationError(space.w_SystemError,
                 space.wrap("libffi failed to build this callback"))
         #
-        # We must setup the GIL here, in case the callback is invoked in
-        # some other non-Pythonic thread.  This is the same as cffi on
-        # CPython.
-        if space.config.translation.thread:
-            from pypy.module.thread.os_thread import setup_threads
-            setup_threads(space)
+        _current_space.space = space
+        handle.get_handles(space).store_handle(handle_index, self)
 
     def _repr_extra(self):
         space = self.space
@@ -127,9 +129,6 @@
             keepalive_until_here(self)   # to keep self._closure.ll_error alive
 
 
-global_callback_mapping = rweakref.RWeakValueDictionary(int, W_CDataCallback)
-
-
 def convert_from_object_fficallback(fresult, ll_res, w_res):
     space = fresult.space
     small_result = fresult.size < SIZE_OF_FFI_ARG
@@ -213,6 +212,12 @@
     except OperationError, e:
         _handle_applevel_exception(callback, e, ll_res, extra_line)
 
+class CurrentSpace:
+    def _cleanup_(self):
+        if hasattr(self, 'space'):
+            del self.space
+_current_space = CurrentSpace()
+
 def _invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
     """ Callback specification.
     ffi_cif - something ffi specific, don't care
@@ -223,8 +228,9 @@
     """
     ll_res = rffi.cast(rffi.CCHARP, ll_res)
     unique_id = rffi.cast(lltype.Signed, ll_userdata)
-    callback = global_callback_mapping.get(unique_id)
-    if callback is None:
+    space = _current_space.space
+    callback = handle.get_handles(space).fetch_handle(unique_id)
+    if callback is None or not isinstance(callback, W_CDataCallback):
         # oups!
         try:
             os.write(STDERR, "SystemError: invoking a callback "
@@ -237,7 +243,6 @@
         return
     #
     must_leave = False
-    space = callback.space
     try:
         must_leave = space.threadlocals.try_enter_thread(space)
         py_invoke_callback(callback, ll_res, ll_args)
diff --git a/pypy/module/_cffi_backend/handle.py b/pypy/module/_cffi_backend/handle.py
--- a/pypy/module/_cffi_backend/handle.py
+++ b/pypy/module/_cffi_backend/handle.py
@@ -9,16 +9,16 @@
     def __init__(self, space):
         self.initialize()
 
-def get(space):
+def get_handles(space):
     return space.fromcache(CffiHandles)
 
 # ____________________________________________________________
 
 def _newp_handle(space, w_ctype, w_x):
-    index = get(space).reserve_next_handle_index()
+    index = get_handles(space).reserve_next_handle_index()
     _cdata = rffi.cast(rffi.CCHARP, index + 1)
     new_cdataobj = cdataobj.W_CDataHandle(space, _cdata, w_ctype, w_x)
-    get(space).store_handle(index, new_cdataobj)
+    get_handles(space).store_handle(index, new_cdataobj)
     return new_cdataobj
 
 @unwrap_spec(w_ctype=ctypeobj.W_CType)
@@ -39,7 +39,7 @@
                     "new_handle(), got '%s'", ctype.name)
     with w_cdata as ptr:
         index = rffi.cast(lltype.Signed, ptr)
-        original_cdataobj = get(space).fetch_handle(index - 1)
+        original_cdataobj = get_handles(space).fetch_handle(index - 1)
     #
     if isinstance(original_cdataobj, cdataobj.W_CDataHandle):
         return original_cdataobj.w_keepalive


More information about the pypy-commit mailing list