Commit b8eb6545 authored by Stefan Behnel's avatar Stefan Behnel

reuse pre-allocated thread locks in critical memoryview creation path

parent a0a3cb4b
...@@ -300,6 +300,24 @@ cdef void *align_pointer(void *memory, size_t alignment) nogil: ...@@ -300,6 +300,24 @@ cdef void *align_pointer(void *memory, size_t alignment) nogil:
return <void *> aligned_p 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') @cname('__pyx_memoryview')
cdef class memoryview(object): cdef class memoryview(object):
...@@ -325,9 +343,14 @@ cdef class memoryview(object): ...@@ -325,9 +343,14 @@ cdef class memoryview(object):
(<__pyx_buffer *> &self.view).obj = Py_None (<__pyx_buffer *> &self.view).obj = Py_None
Py_INCREF(Py_None) Py_INCREF(Py_None)
self.lock = PyThread_allocate_lock() global _thread_locks_used
if self.lock == NULL: if _thread_locks_used < THREAD_LOCKS_PREALLOCATED:
raise MemoryError 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: if flags & PyBUF_FORMAT:
self.dtype_is_object = (self.view.format[0] == b'O' and self.view.format[1] == b'\0') 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): ...@@ -342,8 +365,18 @@ cdef class memoryview(object):
if self.obj is not None: if self.obj is not None:
__Pyx_ReleaseBuffer(&self.view) __Pyx_ReleaseBuffer(&self.view)
cdef int i
global _thread_locks_used
if self.lock != NULL: 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 char *get_item_pointer(memoryview self, object index) except NULL:
cdef Py_ssize_t dim cdef Py_ssize_t dim
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment