pipes:rs: replace unnecessary splice by read-ahead hint

This commit is contained in:
oech3
2026-06-01 12:49:10 +09:00
committed by Daniel Hofstetter
parent 1bb616763a
commit 10ef28ddc1
5 changed files with 14 additions and 21 deletions
+1
View File
@@ -362,6 +362,7 @@ uutils
# * function names
execfn
fadvise
fstatfs
getcwd
mkfifoat
+1 -1
View File
@@ -3,7 +3,7 @@
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat oconv canonicalized fadvise Fadvise FADV DONTNEED ESPIPE bufferedoutput, SETFL
// spell-checker:ignore fname, ftype, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, behaviour, bmax, bremain, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rremain, rsofar, rstat, sigusr, wlen, wstat oconv canonicalized Fadvise FADV DONTNEED ESPIPE bufferedoutput, SETFL
mod blocks;
mod bufferedoutput;
+1 -1
View File
@@ -2,7 +2,7 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
//spell-checker:ignore TAOCP indegree fadvise FADV
//spell-checker:ignore TAOCP indegree FADV
//spell-checker:ignore (libs) interner uclibc
use clap::{Arg, ArgAction, Command};
use rustc_hash::FxHashMap;
+10 -18
View File
@@ -85,17 +85,7 @@ pub fn might_fuse(source: &impl AsFd) -> bool {
/// splice all of source to dest
/// returns Ok(()) at end of file
#[inline]
pub fn splice_unbounded(source: &impl AsFd, dest: &mut impl AsFd) -> rustix::io::Result<()> {
// avoid fcntl overhead for small input. splice twice to catch end of file.
if splice(&source, &dest, MAX_ROOTLESS_PIPE_SIZE)? == 0
|| splice(&source, &dest, MAX_ROOTLESS_PIPE_SIZE)? == 0
{
return Ok(());
}
// fcntl for input would not improve throughput since
// - sender with splice probably increased size already
// - sender without splice is bottleneck
let _ = fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE);
fn splice_unbounded(source: &impl AsFd, dest: &mut impl AsFd) -> rustix::io::Result<()> {
while splice(&source, &dest, MAX_ROOTLESS_PIPE_SIZE)? > 0 {}
Ok(())
}
@@ -104,16 +94,11 @@ pub fn splice_unbounded(source: &impl AsFd, dest: &mut impl AsFd) -> rustix::io:
///
/// This should not be used if one of them are pipe to save resources
#[inline]
pub fn splice_unbounded_broker(source: &impl AsFd, dest: &mut impl AsFd) -> PipeRes {
fn splice_unbounded_broker(source: &impl AsFd, dest: &mut impl AsFd) -> PipeRes {
static PIPE_CACHE: OnceLock<Option<(PipeReader, PipeWriter)>> = OnceLock::new();
let Some((pipe_rd, pipe_wr)) = PIPE_CACHE.get_or_init(|| pipe::<false>().ok()) else {
return Ok(Err(()));
};
// improve throughput
// no need to increase pipe size of input fd since
// - sender with splice probably increased size already
// - sender without splice is bottleneck
let _ = fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE);
loop {
match splice(&source, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
@@ -129,9 +114,16 @@ pub fn splice_unbounded_broker(source: &impl AsFd, dest: &mut impl AsFd) -> Pipe
}
/// try splice_unbounded 1st and splice_unbounded_broker if both of in/output are not pipe
/// This includes read ahead and optimization for stdout's pipe size
#[inline]
pub fn splice_unbounded_auto(source: &impl AsFd, dest: &mut impl AsFd) -> PipeRes {
if splice_unbounded(source, dest).is_err() {
// fcntl for input would not improve throughput since
// - sender with splice probably increased size already
// - sender without splice is bottleneck
let is_pipe_out = fcntl_setpipe_size(&mut *dest, MAX_ROOTLESS_PIPE_SIZE).is_ok();
// pre-generate page caches for splice
let is_file_in = rustix::fs::fadvise(source, 0, None, rustix::fs::Advice::Sequential).is_ok();
if (is_file_in && !is_pipe_out) || splice_unbounded(source, dest).is_err() {
// input or output is not pipe
return splice_unbounded_broker(source, dest);
}
+1 -1
View File
@@ -2,7 +2,7 @@
//
// For the full copyright and license information, please view the LICENSE
// file that was distributed with this source code.
// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, availible, behaviour, bmax, bremain, btotal, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, sigval, wlen, wstat abcdefghijklm abcdefghi nabcde nabcdefg abcdefg fifoname fadvise FADV DONTNEED
// spell-checker:ignore fname, tname, fpath, specfile, testfile, unspec, ifile, ofile, outfile, fullblock, urand, fileio, atoe, atoibm, availible, behaviour, bmax, bremain, btotal, cflags, creat, ctable, ctty, datastructures, doesnt, etoa, fileout, fname, gnudd, iconvflags, iseek, nocache, noctty, noerror, nofollow, nolinks, nonblock, oconvflags, oseek, outfile, parseargs, rlen, rmax, rposition, rremain, rsofar, rstat, sigusr, sigval, wlen, wstat abcdefghijklm abcdefghi nabcde nabcdefg abcdefg fifoname FADV DONTNEED
use uutests::at_and_ucmd;
use uutests::new_ucmd;