Skip to content

Commit b4ac118

Browse files
committed
Optimize frame body extraction to reduce memory copies
Replace BytesIO.read() with direct buffer slicing to eliminate one intermediate bytes allocation per received message frame. Changes: - Use getbuffer() to get memoryview of underlying buffer - Slice directly at [body_offset:end_pos] instead of seek+read - Convert memoryview slice to bytes in single operation - Maintain buffer position tracking for proper reset behavior Benefits: - Eliminates one full-frame allocation on hot receive path - Particularly impactful for large frames (up to 256MB) - Maintains compatibility with existing protocol decoder The memoryview is immediately converted to bytes and released, preventing buffer resize issues while still gaining the allocation savings. Signed-off-by: Yaniv Kaul <ykaul@scylladb.com>
1 parent 0b2ad28 commit b4ac118

1 file changed

Lines changed: 6 additions & 2 deletions

File tree

cassandra/connection.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1260,8 +1260,12 @@ def process_io_buffer(self):
12601260
return
12611261
else:
12621262
frame = self._current_frame
1263-
self._io_buffer.cql_frame_buffer.seek(frame.body_offset)
1264-
msg = self._io_buffer.cql_frame_buffer.read(frame.end_pos - frame.body_offset)
1263+
# Use memoryview to avoid intermediate allocation, then convert to bytes
1264+
# Explicitly scope the buffer to ensure memoryview is released before reset
1265+
cql_buf = self._io_buffer.cql_frame_buffer
1266+
msg = bytes(cql_buf.getbuffer()[frame.body_offset:frame.end_pos])
1267+
# Advance buffer position to end of frame before reset
1268+
cql_buf.seek(frame.end_pos)
12651269
self.process_msg(frame, msg)
12661270
self._io_buffer.reset_cql_frame_buffer()
12671271
self._current_frame = None

0 commit comments

Comments
 (0)