about summary refs log tree commit diff
path: root/library/std/src
diff options
context:
space:
mode:
authorGuillaume Gomez <guillaume1.gomez@gmail.com>2020-12-01 23:46:13 +0100
committerGitHub <noreply@github.com>2020-12-01 23:46:13 +0100
commit9e26fc60b1a91e28e799fd3ed33f8b93db13be2a (patch)
tree3fc34123494ce7c195cd6aac55fb7546f5d18c6f /library/std/src
parent3d631b094bf6322ad77296f843275a06be5e743e (diff)
parent59874516fae2abd97539c2c50601302c6b61ee0f (diff)
downloadrust-9e26fc60b1a91e28e799fd3ed33f8b93db13be2a.tar.gz
rust-9e26fc60b1a91e28e799fd3ed33f8b93db13be2a.zip
Rollup merge of #79600 - nicokoch:kernel_copy_unixstream, r=m-ou-se
std::io: Use sendfile for UnixStream

`UnixStream` was forgotten in #75272 .

Benchmark yields the following results.
Before:
`running 1 test
test sys::unix::kernel_copy::tests::bench_file_to_uds_copy        ... bench:      54,399 ns/iter (+/- 6,817) = 2409 MB/s`

After:
`running 1 test
test sys::unix::kernel_copy::tests::bench_file_to_uds_copy        ... bench:      18,627 ns/iter (+/- 6,007) = 7036 MB/s`
Diffstat (limited to 'library/std/src')
-rw-r--r--library/std/src/sys/unix/kernel_copy.rs29
-rw-r--r--library/std/src/sys/unix/kernel_copy/tests.rs29
2 files changed, 58 insertions, 0 deletions
diff --git a/library/std/src/sys/unix/kernel_copy.rs b/library/std/src/sys/unix/kernel_copy.rs
index 1dc16ef0993..f08c828ecff 100644
--- a/library/std/src/sys/unix/kernel_copy.rs
+++ b/library/std/src/sys/unix/kernel_copy.rs
@@ -56,6 +56,7 @@ use crate::mem::ManuallyDrop;
 use crate::net::TcpStream;
 use crate::os::unix::fs::FileTypeExt;
 use crate::os::unix::io::{AsRawFd, FromRawFd, RawFd};
+use crate::os::unix::net::UnixStream;
 use crate::process::{ChildStderr, ChildStdin, ChildStdout};
 use crate::ptr;
 use crate::sync::atomic::{AtomicBool, Ordering};
@@ -320,6 +321,34 @@ impl CopyWrite for &TcpStream {
     }
 }
 
+impl CopyRead for UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyRead for &UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
+impl CopyWrite for &UnixStream {
+    fn properties(&self) -> CopyParams {
+        // avoid the stat syscall since we can be fairly sure it's a socket
+        CopyParams(FdMeta::Socket, Some(self.as_raw_fd()))
+    }
+}
+
 impl CopyWrite for ChildStdin {
     fn properties(&self) -> CopyParams {
         CopyParams(FdMeta::Pipe, Some(self.as_raw_fd()))
diff --git a/library/std/src/sys/unix/kernel_copy/tests.rs b/library/std/src/sys/unix/kernel_copy/tests.rs
index 21b121c26ff..554ebd94022 100644
--- a/library/std/src/sys/unix/kernel_copy/tests.rs
+++ b/library/std/src/sys/unix/kernel_copy/tests.rs
@@ -118,6 +118,35 @@ fn bench_file_to_socket_copy(b: &mut test::Bencher) {
     });
 }
 
+#[bench]
+fn bench_file_to_uds_copy(b: &mut test::Bencher) {
+    const BYTES: usize = 128 * 1024;
+    let src_path = temp_dir().join("uds-copy-bench-src");
+    let mut src = OpenOptions::new()
+        .create(true)
+        .truncate(true)
+        .read(true)
+        .write(true)
+        .open(src_path)
+        .unwrap();
+    src.write(&vec![0u8; BYTES]).unwrap();
+
+    let (mut sink, mut sink_drainer) = crate::os::unix::net::UnixStream::pair().unwrap();
+
+    crate::thread::spawn(move || {
+        let mut sink_buf = vec![0u8; 1024 * 1024];
+        loop {
+            sink_drainer.read(&mut sink_buf[..]).unwrap();
+        }
+    });
+
+    b.bytes = BYTES as u64;
+    b.iter(|| {
+        src.seek(SeekFrom::Start(0)).unwrap();
+        assert_eq!(BYTES as u64, io::copy(&mut src, &mut sink).unwrap());
+    });
+}
+
 #[cfg(any(target_os = "linux", target_os = "android"))]
 #[bench]
 fn bench_socket_pipe_socket_copy(b: &mut test::Bencher) {