Sherlock-Holo / fuse3

an async version fuse library for rust
MIT License
83 stars 17 forks source link

Double data copy due to combined header and data buffers #10

Open asomers opened 3 years ago

asomers commented 3 years ago

Most of the methods of Session create a Vec and copy two slices into it: the fuse_out_header and an opcode-specific response. However, this Vec is short-lived: its contents get copied again by nix::unistd::write to the fuse device. I suggest eliminating the first data copy by changing the Session::response_sender's type to include separate buffers for the header and the data. Then use nix::unistd::writev to pass them to the kernel. It would look like this:

pub struct Session<'a, FS> {
    ...
    response_sender: UnboundedSender<(fuse_out_header, Vec)>,
    ...
}
impl FuseConnection {
        pub async fn write(&self, response: (fuse_out_header, Vec) -> Result<usize, io::Error> {
            let _guard = self.write.lock().await;

            let header_data = get_bincode_config()
                .serialize(&response.0)
                .unwrap();
            let iovecs = [IoVec::from_slice(&header_data), IoVec::from_slice(&response.1)];
            loop {
                let mut write_guard = self.fd.writable().await?;
                if let Ok(result) = write_guard.try_io(|fd| {
                    unistd::writev(fd.as_raw_fd(), &iovecs).map_err(io::Error::from)
                }) {
                    return result;
                } else {
                    continue;
                }
            }
        }

}