From 3dcf989f96fdbb765e4c1a2b86e5145b96632e23 Mon Sep 17 00:00:00 2001 From: Petros Angelatos Date: Wed, 9 Apr 2025 14:03:58 +0300 Subject: [PATCH] postgres-replication: reuse underlying allocation for tuple data The logical replication parsing routine for tuple data left some performance on the table by copying the replication data into new allocations instead of reusing the ones provided by the underlying `Bytes` buffer. Signed-off-by: Petros Angelatos --- postgres-replication/src/protocol.rs | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/postgres-replication/src/protocol.rs b/postgres-replication/src/protocol.rs index 2344f3721..3f3899121 100644 --- a/postgres-replication/src/protocol.rs +++ b/postgres-replication/src/protocol.rs @@ -442,9 +442,8 @@ impl TupleData { TUPLE_DATA_TOAST_TAG => TupleData::UnchangedToast, TUPLE_DATA_TEXT_TAG => { let len = buf.read_i32::()?; - let mut data = vec![0; len as usize]; - buf.read_exact(&mut data)?; - TupleData::Text(data.into()) + let data = buf.read_buf(len as usize)?; + TupleData::Text(data) } TUPLE_DATA_BINARY_TAG => { let len = buf.read_i32::()?; @@ -778,6 +777,20 @@ impl Buffer { self.idx = self.bytes.len(); buf } + + #[inline] + fn read_buf(&mut self, len: usize) -> io::Result { + if self.idx + len <= self.bytes.len() { + let buf = self.bytes.slice(self.idx..(self.idx + len)); + self.idx += len; + Ok(buf) + } else { + Err(io::Error::new( + io::ErrorKind::UnexpectedEof, + "unexpected EOF", + )) + } + } } impl Read for Buffer {