From 2a3fa0955fc5db6bfc1705f4f277bd36a1cf57db Mon Sep 17 00:00:00 2001 From: PThorpe92 Date: Mon, 4 Aug 2025 16:18:19 -0400 Subject: [PATCH] Attempt to coalesce contiguous iovecs during pwritev operation for unix IO --- core/io/unix.rs | 37 +++++++++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/core/io/unix.rs b/core/io/unix.rs index 15bef64f0..cde493514 100644 --- a/core/io/unix.rs +++ b/core/io/unix.rs @@ -207,19 +207,44 @@ fn try_pwritev_raw( ) -> std::io::Result { const MAX_IOV: usize = 1024; let iov_len = std::cmp::min(bufs.len() - start_idx, MAX_IOV); - let mut iov = Vec::with_capacity(iov_len); + let mut iov: Vec = Vec::with_capacity(iov_len); + let mut last_end: Option<(*const u8, usize)> = None; + let mut iov_count = 0; for (i, b) in bufs.iter().enumerate().skip(start_idx).take(iov_len) { let r = b.borrow(); // borrow just to get pointer/len let s = r.as_slice(); - let s = if i == start_idx { &s[start_off..] } else { s }; + let ptr = if i == start_idx { &s[start_off..] } else { s }.as_ptr(); + let len = r.len(); + + if let Some((last_ptr, last_len)) = last_end { + // Check if this buffer is adjacent to the last + if unsafe { last_ptr.add(last_len) } == ptr { + // Extend the last iovec instead of adding new + iov[iov_count - 1].iov_len += len; + last_end = Some((last_ptr, last_len + len)); + continue; + } + } + last_end = Some((ptr, len)); + iov_count += 1; iov.push(libc::iovec { - iov_base: s.as_ptr() as *mut _, - iov_len: s.len(), + iov_base: ptr as *mut libc::c_void, + iov_len: len, }); } - - let n = unsafe { libc::pwritev(fd, iov.as_ptr(), iov.len() as i32, off as i64) }; + let n = if iov.len().eq(&1) { + unsafe { + libc::pwrite( + fd, + iov[0].iov_base as *const libc::c_void, + iov[0].iov_len, + off as i64, + ) + } + } else { + unsafe { libc::pwritev(fd, iov.as_ptr(), iov.len() as i32, off as i64) } + }; if n < 0 { Err(std::io::Error::last_os_error()) } else {