Skip to content

Commit e4331a4

Browse files
oech3oech3
authored andcommitted
cat: improve splice fast-path
1 parent 3dec656 commit e4331a4

File tree

3 files changed

+18
-5
lines changed

3 files changed

+18
-5
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,7 @@ weblate
369369
algs
370370
wasm
371371
wasip
372+
SETPIPE
372373

373374
# * stty terminal flags
374375
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: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,28 @@
55

66
//! Thin pipe-related wrappers around functions from the `nix` crate.
77
8+
#[cfg(any(target_os = "linux", target_os = "android"))]
9+
use nix::fcntl::{FcntlArg, SpliceFFlags, fcntl};
10+
#[cfg(any(target_os = "linux", target_os = "android"))]
811
use std::fs::File;
912
#[cfg(any(target_os = "linux", target_os = "android"))]
1013
use std::os::fd::AsFd;
11-
1214
#[cfg(any(target_os = "linux", target_os = "android"))]
13-
use nix::fcntl::SpliceFFlags;
15+
pub const MAX_ROOTLESS_PIPE_SIZE: usize = 1024 * 1024;
1416

1517
pub use nix::{Error, Result};
1618

1719
/// A wrapper around [`nix::unistd::pipe`] that ensures the pipe is cleaned up.
1820
///
1921
/// Returns two `File` objects: everything written to the second can be read
2022
/// from the first.
23+
/// This is used only for resolving the limitation for splice: one of a input or output should be pipe
24+
#[cfg(any(target_os = "linux", target_os = "android"))]
2125
pub fn pipe() -> Result<(File, File)> {
2226
let (read, write) = nix::unistd::pipe()?;
27+
// improve performance for splice
28+
let _ = fcntl(&read, FcntlArg::F_SETPIPE_SZ(MAX_ROOTLESS_PIPE_SIZE as i32));
29+
2330
Ok((File::from(read), File::from(write)))
2431
}
2532

0 commit comments

Comments
 (0)