@@ -13,8 +13,12 @@ use uucore::error::{UResult, USimpleError};
1313use uucore:: format_usage;
1414use uucore:: translate;
1515
16- // it's possible that using a smaller or larger buffer might provide better performance on some
17- // systems, but honestly this is good enough
16+ #[ cfg( target_os = "linux" ) ]
17+ const MAX_ROOTLESS_PIPE_SIZE : usize = 1024 * 1024 ;
18+ // todo: investigate best rate
19+ #[ cfg( target_os = "linux" ) ]
20+ const BUF_SIZE : usize = MAX_ROOTLESS_PIPE_SIZE ;
21+ #[ cfg( not( target_os = "linux" ) ) ]
1822const BUF_SIZE : usize = 16 * 1024 ;
1923
2024#[ uucore:: main]
@@ -110,8 +114,30 @@ fn prepare_buffer(buf: &mut Vec<u8>) {
110114
111115pub fn exec ( bytes : & [ u8 ] ) -> io:: Result < ( ) > {
112116 let stdout = io:: stdout ( ) ;
113- let mut stdout = stdout. lock ( ) ;
117+ #[ cfg( target_os = "linux" ) ]
118+ {
119+ use rustix:: io:: write;
120+ use rustix:: pipe:: { SpliceFlags , fcntl_setpipe_size, pipe, tee} ;
121+ // fast-path for pipe
122+ if bytes. len ( ) < MAX_ROOTLESS_PIPE_SIZE * 4
123+ && let Ok ( ( p_read, p_write) ) = pipe ( )
124+ {
125+ let _ = fcntl_setpipe_size ( & p_read, MAX_ROOTLESS_PIPE_SIZE ) ;
126+ let _ = fcntl_setpipe_size ( & p_write, MAX_ROOTLESS_PIPE_SIZE ) ;
127+ let _ = fcntl_setpipe_size ( & stdout, MAX_ROOTLESS_PIPE_SIZE ) ;
128+ let _ = write ( & p_write, bytes) ;
129+ loop {
130+ match tee ( & p_read, & stdout, MAX_ROOTLESS_PIPE_SIZE , SpliceFlags :: MORE ) {
131+ Ok ( n) if n > 0 => { }
132+ Ok ( 0 ) => break ,
133+ Err ( e) if e. kind ( ) == io:: ErrorKind :: Interrupted => continue ,
134+ _ => break ,
135+ }
136+ }
137+ }
138+ }
114139
140+ let mut stdout = stdout. lock ( ) ;
115141 loop {
116142 stdout. write_all ( bytes) ?;
117143 }
@@ -122,6 +148,7 @@ mod tests {
122148 use super :: * ;
123149
124150 #[ test]
151+ #[ cfg( not( target_os = "linux" ) ) ] // Linux uses different buffer size
125152 fn test_prepare_buffer ( ) {
126153 let tests = [
127154 ( 150 , 16350 ) ,
0 commit comments