From b8eb6545b5db4048799e337766246026ac695dcb Mon Sep 17 00:00:00 2001 From: Stefan Behnel <stefan_ml@behnel.de> Date: Mon, 26 Oct 2015 20:30:56 +0100 Subject: [PATCH] reuse pre-allocated thread locks in critical memoryview creation path --- Cython/Utility/MemoryView.pyx | 41 +++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Cython/Utility/MemoryView.pyx b/Cython/Utility/MemoryView.pyx index 27bc11f67..f6e7ee811 100644 --- a/Cython/Utility/MemoryView.pyx +++ b/Cython/Utility/MemoryView.pyx @@ -300,6 +300,24 @@ cdef void *align_pointer(void *memory, size_t alignment) nogil: return <void *> aligned_p + +# pre-allocate thread locks for reuse +## note that this could be implemented in a more beautiful way in "normal" Cython, +## but this code gets merged into the user module and not everything works there. +DEF THREAD_LOCKS_PREALLOCATED = 8 +cdef int _thread_locks_used = 0 +cdef PyThread_type_lock[THREAD_LOCKS_PREALLOCATED] _thread_locks = [ + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), + PyThread_allocate_lock(), +] + + @cname('__pyx_memoryview') cdef class memoryview(object): @@ -325,9 +343,14 @@ cdef class memoryview(object): (<__pyx_buffer *> &self.view).obj = Py_None Py_INCREF(Py_None) - self.lock = PyThread_allocate_lock() - if self.lock == NULL: - raise MemoryError + global _thread_locks_used + if _thread_locks_used < THREAD_LOCKS_PREALLOCATED: + self.lock = _thread_locks[_thread_locks_used] + _thread_locks_used += 1 + if self.lock is NULL: + self.lock = PyThread_allocate_lock() + if self.lock is NULL: + raise MemoryError if flags & PyBUF_FORMAT: self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') @@ -342,8 +365,18 @@ cdef class memoryview(object): if self.obj is not None: __Pyx_ReleaseBuffer(&self.view) + cdef int i + global _thread_locks_used if self.lock != NULL: - PyThread_free_lock(self.lock) + for i in range(_thread_locks_used): + if _thread_locks[i] is self.lock: + _thread_locks_used -= 1 + if i != _thread_locks_used: + _thread_locks[i], _thread_locks[_thread_locks_used] = ( + _thread_locks[_thread_locks_used], _thread_locks[i]) + break + else: + PyThread_free_lock(self.lock) cdef char *get_item_pointer(memoryview self, object index) except NULL: cdef Py_ssize_t dim -- 2.30.9