Skip to content

Commit 54cded3

Browse files
committed
improved performance
1 parent 93eaaaa commit 54cded3

File tree

2 files changed

+99
-28
lines changed

2 files changed

+99
-28
lines changed

python_hackrf/pylibhackrf/pyhackrf.pyx

Lines changed: 49 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,9 @@
2222

2323
# cython: language_level=3str
2424
from python_hackrf import __version__
25-
from libc.stdint cimport int8_t, uint8_t, uint16_t, uint32_t, uint64_t
25+
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
2626
from libc.stdlib cimport malloc, free
27+
from libc.string cimport memcpy
2728
from enum import IntEnum
2829
from ctypes import c_int
2930
from . cimport chackrf
@@ -91,12 +92,22 @@ class py_operacake_ports(IntEnum):
9192

9293
@cython.boundscheck(False)
9394
@cython.wraparound(False)
94-
cdef int __rx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
95+
cdef int __rx_callback(chackrf.hackrf_transfer *transfer) nogil:
9596
global global_callbacks
97+
cdef uint8_t* buffer_ptr = transfer.buffer
98+
cdef uint8_t* np_buffer_ptr
9699
cdef int result = -1
97100

98101
with gil:
99-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
102+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
103+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
104+
105+
memcpy(
106+
np_buffer_ptr,
107+
buffer_ptr,
108+
transfer.valid_length,
109+
)
110+
100111
if global_callbacks[<size_t> transfer.device]['__rx_callback'] is not None:
101112
result = global_callbacks[<size_t> transfer.device]['__rx_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length)
102113

@@ -105,37 +116,50 @@ cdef int __rx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
105116

106117
@cython.boundscheck(False)
107118
@cython.wraparound(False)
108-
cdef int __tx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
119+
cdef int __tx_callback(chackrf.hackrf_transfer *transfer) nogil:
109120
global global_callbacks
110-
cdef int8_t[:] cython_view
121+
cdef uint8_t* buffer_ptr = transfer.buffer
122+
cdef uint8_t* np_buffer_ptr
111123
cdef int result = -1
112-
cdef int i
113124

114125
with gil:
115-
valid_length = c_int(transfer.valid_length)
116126
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
117-
cython_view = np_buffer
127+
valid_length = c_int(transfer.valid_length)
128+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
118129

119130
if global_callbacks[<size_t> transfer.device]['__tx_callback'] is not None:
120131
result = global_callbacks[<size_t> transfer.device]['__tx_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, valid_length)
121132
transfer.valid_length = valid_length.value
122133
else:
123134
transfer.valid_length = 0
124135

125-
for i in range(transfer.valid_length):
126-
transfer.buffer[i] = <uint8_t> cython_view[i]
136+
memcpy(
137+
buffer_ptr,
138+
np_buffer_ptr,
139+
transfer.valid_length
140+
)
127141

128142
return result
129143

130144

131145
@cython.boundscheck(False)
132146
@cython.wraparound(False)
133-
cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
147+
cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) nogil:
134148
global global_callbacks
149+
cdef uint8_t* buffer_ptr = transfer.buffer
150+
cdef uint8_t* np_buffer_ptr
135151
cdef int result = -1
136152

137153
with gil:
138-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
154+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
155+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
156+
157+
memcpy(
158+
np_buffer_ptr,
159+
buffer_ptr,
160+
transfer.valid_length,
161+
)
162+
139163
if global_callbacks[<size_t> transfer.device]['__sweep_callback'] is not None:
140164
result = global_callbacks[<size_t> transfer.device]['__sweep_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length)
141165

@@ -144,11 +168,21 @@ cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
144168

145169
@cython.boundscheck(False)
146170
@cython.wraparound(False)
147-
cdef void __tx_complete_callback(chackrf.hackrf_transfer *transfer, int success) noexcept nogil:
171+
cdef void __tx_complete_callback(chackrf.hackrf_transfer *transfer, int success) nogil:
148172
global global_callbacks
173+
cdef uint8_t* buffer_ptr = transfer.buffer
174+
cdef uint8_t* np_buffer_ptr
149175

150176
with gil:
151-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
177+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
178+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
179+
180+
memcpy(
181+
np_buffer_ptr,
182+
buffer_ptr,
183+
transfer.valid_length,
184+
)
185+
152186
if global_callbacks[<size_t> transfer.device]['__tx_complete_callback'] is not None:
153187
global_callbacks[<size_t> transfer.device]['__tx_complete_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length, success)
154188

@@ -193,6 +227,7 @@ cdef class PyHackRFDeviceList:
193227
if self.__hackrf_device_list is not NULL:
194228
return chackrf.hackrf_board_id_name(self.__hackrf_device_list[0].usb_board_ids[index]).decode('utf-8')
195229

230+
196231
cdef class PyHackrfDevice:
197232

198233
cdef chackrf.hackrf_device *__hackrf_device

python_hackrf/pylibhackrf/pyhackrf_android.pyx

Lines changed: 50 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,11 @@
2222

2323
# cython: language_level=3str
2424
from python_hackrf import __version__
25-
from libc.stdint cimport int8_t, uint8_t, uint16_t, uint32_t, uint64_t
25+
from libc.stdint cimport uint8_t, uint16_t, uint32_t, uint64_t, uintptr_t
2626
from .__android import get_hackrf_device_list
2727
from . cimport chackrf_android as chackrf
2828
from libc.stdlib cimport malloc, free
29+
from libc.string cimport memcpy
2930
from enum import IntEnum
3031
from ctypes import c_int
3132
import numpy as np
@@ -92,12 +93,22 @@ class py_operacake_ports(IntEnum):
9293

9394
@cython.boundscheck(False)
9495
@cython.wraparound(False)
95-
cdef int __rx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
96+
cdef int __rx_callback(chackrf.hackrf_transfer *transfer) nogil:
9697
global global_callbacks
98+
cdef uint8_t* buffer_ptr = transfer.buffer
99+
cdef uint8_t* np_buffer_ptr
97100
cdef int result = -1
98101

99102
with gil:
100-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
103+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
104+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
105+
106+
memcpy(
107+
np_buffer_ptr,
108+
buffer_ptr,
109+
transfer.valid_length,
110+
)
111+
101112
if global_callbacks[<size_t> transfer.device]['__rx_callback'] is not None:
102113
result = global_callbacks[<size_t> transfer.device]['__rx_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length)
103114

@@ -106,35 +117,50 @@ cdef int __rx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
106117

107118
@cython.boundscheck(False)
108119
@cython.wraparound(False)
109-
cdef int __tx_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
120+
cdef int __tx_callback(chackrf.hackrf_transfer *transfer) nogil:
110121
global global_callbacks
111-
cdef int8_t[:] cython_view
122+
cdef uint8_t* buffer_ptr = transfer.buffer
123+
cdef uint8_t* np_buffer_ptr
112124
cdef int result = -1
113-
cdef int i
114125

115126
with gil:
116-
valid_length = c_int(transfer.valid_length)
117127
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
118-
cython_view = np_buffer
128+
valid_length = c_int(transfer.valid_length)
129+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
119130

120131
if global_callbacks[<size_t> transfer.device]['__tx_callback'] is not None:
121132
result = global_callbacks[<size_t> transfer.device]['__tx_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, valid_length)
122133
transfer.valid_length = valid_length.value
134+
else:
135+
transfer.valid_length = 0
123136

124-
for i in range(transfer.valid_length):
125-
transfer.buffer[i] = <uint8_t> cython_view[i]
137+
memcpy(
138+
buffer_ptr,
139+
np_buffer_ptr,
140+
transfer.valid_length
141+
)
126142

127143
return result
128144

129145

130146
@cython.boundscheck(False)
131147
@cython.wraparound(False)
132-
cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
148+
cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) nogil:
133149
global global_callbacks
150+
cdef uint8_t* buffer_ptr = transfer.buffer
151+
cdef uint8_t* np_buffer_ptr
134152
cdef int result = -1
135153

136154
with gil:
137-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
155+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
156+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
157+
158+
memcpy(
159+
np_buffer_ptr,
160+
buffer_ptr,
161+
transfer.valid_length,
162+
)
163+
138164
if global_callbacks[<size_t> transfer.device]['__sweep_callback'] is not None:
139165
result = global_callbacks[<size_t> transfer.device]['__sweep_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length)
140166

@@ -143,11 +169,21 @@ cdef int __sweep_callback(chackrf.hackrf_transfer *transfer) noexcept nogil:
143169

144170
@cython.boundscheck(False)
145171
@cython.wraparound(False)
146-
cdef void __tx_complete_callback(chackrf.hackrf_transfer *transfer, int success) noexcept nogil:
172+
cdef void __tx_complete_callback(chackrf.hackrf_transfer *transfer, int success) nogil:
147173
global global_callbacks
174+
cdef uint8_t* buffer_ptr = transfer.buffer
175+
cdef uint8_t* np_buffer_ptr
148176

149177
with gil:
150-
np_buffer = np.asarray(<uint8_t[:transfer.buffer_length]> transfer.buffer, dtype=np.int8) # type: ignore
178+
np_buffer = np.empty(transfer.buffer_length, dtype=np.int8)
179+
np_buffer_ptr = <uint8_t*> <uintptr_t> np_buffer.ctypes.data
180+
181+
memcpy(
182+
np_buffer_ptr,
183+
buffer_ptr,
184+
transfer.valid_length,
185+
)
186+
151187
if global_callbacks[<size_t> transfer.device]['__tx_complete_callback'] is not None:
152188
global_callbacks[<size_t> transfer.device]['__tx_complete_callback'](global_callbacks[<size_t> transfer.device]['device'], np_buffer, transfer.buffer_length, transfer.valid_length, success)
153189

0 commit comments

Comments
 (0)