fast_io.rs: use sendfile or splice if copy_file_range is not supported - #459
Conversation
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #459 +/- ##
==========================================
- Coverage 82.18% 81.85% -0.33%
==========================================
Files 13 13
Lines 5551 5743 +192
Branches 312 323 +11
==========================================
+ Hits 4562 4701 +139
- Misses 986 1039 +53
Partials 3 3
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
- Use `splice` and attempt to expand the pipe size when necessary. - Modify the `reliable_copy_file_range()` function to sequentially attempt `copy_file_range` → `splice` → `sendfile` → `write`. - Add Linux-based unit tests. Closes: uutils#443
cee18ce to
581e725
Compare
|
sendfile is internally splice. So no worth to try it. splice with middler pipe is faster. |
|
Please use rustix instead of unsafe libc. |
|
|
||
| /// Wrapper to get current pipe buffer size | ||
| #[cfg(all(target_os = "linux", target_env = "gnu"))] | ||
| fn get_pipe_size(fd: i32) -> std::io::Result<usize> { |
There was a problem hiding this comment.
No need to get size. Use set only without checking 1st size.
| fn set_pipe_size(fd: i32, size: usize) -> std::io::Result<()> { | ||
| let ret = unsafe { libc::fcntl(fd, libc::F_SETPIPE_SZ, size as libc::c_int) }; | ||
| if ret < 0 { | ||
| Err(io::Error::last_os_error()) |
There was a problem hiding this comment.
larger pipe size is not a strong requirement. So Err(()) is enough.
| out_fd, | ||
| std::ptr::null_mut(), | ||
| len, | ||
| libc::SPLICE_F_MOVE | libc::SPLICE_F_MORE, |
There was a problem hiding this comment.
| libc::SPLICE_F_MOVE | libc::SPLICE_F_MORE, | |
| libc::SPLICE_F_MORE, |
Dummy flag. Do nothing.
| fn test_get_pipe_size_from_pipe() { | ||
| // Create a pipe | ||
| let mut fds = [0; 2]; | ||
| assert_eq!(unsafe { libc::pipe(fds.as_mut_ptr()) }, 0); |
| // Try to extend pipe buffer size if output is a pipe | ||
| // This helps improve throughput when writing to pipes | ||
| if let Ok(current_size) = get_pipe_size(out_fd) { | ||
| let desired_size = 1024 * 1024; // 1 MiB | ||
| if current_size < desired_size { | ||
| let _ = set_pipe_size(out_fd, desired_size); | ||
| } | ||
| } |
There was a problem hiding this comment.
| // Try to extend pipe buffer size if output is a pipe | |
| // This helps improve throughput when writing to pipes | |
| if let Ok(current_size) = get_pipe_size(out_fd) { | |
| let desired_size = 1024 * 1024; // 1 MiB | |
| if current_size < desired_size { | |
| let _ = set_pipe_size(out_fd, desired_size); | |
| } | |
| } | |
| // Try to extend pipe buffer size if output is a pipe | |
| // This helps improve throughput when writing to pipes | |
| const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024; | |
| let _ = set_pipe_size(out_fd, MAX_ROOTLESS_PIPE_SIZE); |
|
|
||
| // Clean up | ||
| unsafe { | ||
| libc::close(read_fd); |
There was a problem hiding this comment.
Not required if std::io::pipe is used
spliceand attempt to expand the pipe size when necessary.reliable_copy_file_range()function to sequentially attemptcopy_file_range→splice→sendfile→write.Closes: #443