Skip to content

Commit 11e1310

Browse files
committed
cat: improve splice fast-path
1 parent 04b1585 commit 11e1310

File tree

3 files changed

+15
-4
lines changed

3 files changed

+15
-4
lines changed

.vscode/cspell.dictionaries/workspace.wordlist.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,7 @@ weblate
374374
algs
375375
wasm
376376
wasip
377+
SETPIPE
377378

378379
# * stty terminal flags
379380
brkint

src/uu/cat/src/splice.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,8 @@ use super::{CatResult, FdReadable, InputHandle};
77
use nix::unistd;
88
use std::os::{fd::AsFd, unix::io::AsRawFd};
99

10-
use uucore::pipes::{pipe, splice, splice_exact};
10+
use uucore::pipes::{MAX_ROOTLESS_PIPE_SIZE, pipe, splice, splice_exact};
1111

12-
const SPLICE_SIZE: usize = 1024 * 128;
1312
const BUF_SIZE: usize = 1024 * 16;
1413

1514
/// This function is called from `write_fast()` on Linux and Android. The
@@ -24,10 +23,16 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
2423
handle: &InputHandle<R>,
2524
write_fd: &S,
2625
) -> CatResult<bool> {
26+
use nix::fcntl::{FcntlArg, fcntl};
2727
let (pipe_rd, pipe_wr) = pipe()?;
28+
// improve performance
29+
let _ = fcntl(
30+
write_fd,
31+
FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32),
32+
);
2833

2934
loop {
30-
match splice(&handle.reader, &pipe_wr, SPLICE_SIZE) {
35+
match splice(&handle.reader, &pipe_wr, MAX_ROOTLESS_PIPE_SIZE) {
3136
Ok(n) => {
3237
if n == 0 {
3338
return Ok(false);

src/uucore/src/lib/features/pipes.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,26 @@
44
// file that was distributed with this source code.
55

66
//! Thin zero-copy-related wrappers around functions from the `rustix` crate.
7+
78
#[cfg(any(target_os = "linux", target_os = "android"))]
89
use std::fs::File;
910
#[cfg(any(target_os = "linux", target_os = "android"))]
1011
use std::os::fd::AsFd;
11-
1212
#[cfg(any(target_os = "linux", target_os = "android"))]
1313
use rustix::pipe::SpliceFlags;
14+
pub const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024;
1415

1516
/// A wrapper around [`rustix::pipe::pipe`] that ensures the pipe is cleaned up.
1617
///
1718
/// Returns two `File` objects: everything written to the second can be read
1819
/// from the first.
20+
/// This is used only for resolving the limitation for splice: one of a input or output should be pipe
1921
#[cfg(any(target_os = "linux", target_os = "android"))]
2022
pub fn pipe() -> std::io::Result<(File, File)> {
2123
let (read, write) = rustix::pipe::pipe()?;
24+
// improve performance for splice
25+
let _ = fcntl(&read, FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32));
26+
2227
Ok((File::from(read), File::from(write)))
2328
}
2429

0 commit comments

Comments
 (0)