From 7ff3579b91843322e22d31c7da93339bcac04975 Mon Sep 17 00:00:00 2001 From: keithcat1 Date: Thu, 3 Mar 2022 12:55:21 -0600 Subject: [PATCH 1/4] Optimize Stream.create_stream_from_file_obj by using file.readinto() to copy data straight into the callback-provided output buffer without any kind of allocation. --- Bass4Py/bass/stream.pyx | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/Bass4Py/bass/stream.pyx b/Bass4Py/bass/stream.pyx index 8b4898a7..ae7674df 100644 --- a/Bass4Py/bass/stream.pyx +++ b/Bass4Py/bass/stream.pyx @@ -1,5 +1,4 @@ from libc.string cimport memmove - from ..bindings.bass cimport ( _BASS_ATTRIB_BITRATE, _BASS_ATTRIB_NET_RESUME, @@ -97,18 +96,12 @@ cdef QWORD __stdcall CFILELENPROC_STD(void *user) with gil: cdef DWORD CFILEREADPROC(void *buffer, DWORD length, void *user) with gil: cdef Stream strm = user - cdef bytes data cdef DWORD blen - + cdef unsigned char[:] buffer_memoryview = buffer # make memoryview, using buffer as the memory try: - data = strm._file.read(length) - blen = len(data) + blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer + - if blen > length: - data = data[:length] - blen = length - - memmove(buffer, data, blen) return blen except Exception: warnings.warn(traceback.format_exc(), RuntimeWarning) From af93ddf3cf8f3ac8c966f8b845e59ae530ba3cda Mon Sep 17 00:00:00 2001 From: keithcat1 Date: Sat, 5 Mar 2022 12:40:16 -0600 Subject: [PATCH 2/4] bass.Stream.create_stream_from_file_obj: if readinto() is not available, use read() instead --- Bass4Py/bass/stream.pyx | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Bass4Py/bass/stream.pyx b/Bass4Py/bass/stream.pyx index ae7674df..c0537967 100644 --- a/Bass4Py/bass/stream.pyx +++ b/Bass4Py/bass/stream.pyx @@ -98,10 +98,13 @@ cdef DWORD CFILEREADPROC(void *buffer, DWORD length, void *user) with gil: cdef Stream strm = user cdef DWORD blen cdef unsigned char[:] buffer_memoryview = buffer # make memoryview, using buffer as the memory + cdef const unsigned char[:] bytes_memoryview # if readinto() is not available, we'll put the result of read() in this variable and copy the data try: - blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer - - + if hasattr(strm.file, "readinto"): blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer + elif hasattr(strm.file, "read"): + bytes_memoryview = strm.file.read(len) + len = bytes_memoryview.shape[0] # we might not've gotten as much data as requested + buffer_memoryview[:len] = bytes_memoryview[:len] # let Cython copy the data for us return blen except Exception: warnings.warn(traceback.format_exc(), RuntimeWarning) From ea23f3482a48ea20e0a0e496601b26ce29fc5e1e Mon Sep 17 00:00:00 2001 From: keithcat1 Date: Tue, 8 Mar 2022 12:57:28 -0600 Subject: [PATCH 3/4] Fix use of wrong variable name --- Bass4Py/bass/stream.pyx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Bass4Py/bass/stream.pyx b/Bass4Py/bass/stream.pyx index c0537967..99f24a3e 100644 --- a/Bass4Py/bass/stream.pyx +++ b/Bass4Py/bass/stream.pyx @@ -102,7 +102,7 @@ cdef DWORD CFILEREADPROC(void *buffer, DWORD length, void *user) with gil: try: if hasattr(strm.file, "readinto"): blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer elif hasattr(strm.file, "read"): - bytes_memoryview = strm.file.read(len) + bytes_memoryview = strm.file.read(length) len = bytes_memoryview.shape[0] # we might not've gotten as much data as requested buffer_memoryview[:len] = bytes_memoryview[:len] # let Cython copy the data for us return blen From 6567f290dcdb16b8d80d570d9668894ceca4dee3 Mon Sep 17 00:00:00 2001 From: keithcat1 Date: Fri, 11 Mar 2022 16:49:31 -0600 Subject: [PATCH 4/4] Fix wrong use of attribute name. --- Bass4Py/bass/stream.pyx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Bass4Py/bass/stream.pyx b/Bass4Py/bass/stream.pyx index 99f24a3e..4602b456 100644 --- a/Bass4Py/bass/stream.pyx +++ b/Bass4Py/bass/stream.pyx @@ -100,9 +100,9 @@ cdef DWORD CFILEREADPROC(void *buffer, DWORD length, void *user) with gil: cdef unsigned char[:] buffer_memoryview = buffer # make memoryview, using buffer as the memory cdef const unsigned char[:] bytes_memoryview # if readinto() is not available, we'll put the result of read() in this variable and copy the data try: - if hasattr(strm.file, "readinto"): blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer - elif hasattr(strm.file, "read"): - bytes_memoryview = strm.file.read(length) + if hasattr(strm._file, "readinto"): blen = strm._file.readinto(buffer_memoryview) # read data directly from file into the buffer + elif hasattr(strm._file, "read"): + bytes_memoryview = strm._file.read(length) len = bytes_memoryview.shape[0] # we might not've gotten as much data as requested buffer_memoryview[:len] = bytes_memoryview[:len] # let Cython copy the data for us return blen