@@ -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( any( target_os = "linux" , target_os = "android" ) ) ]
17+ const MAX_ROOTLESS_PIPE_SIZE : usize = 1024 * 1024 ;
18+ // todo: investigate best rate
19+ #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
20+ const BUF_SIZE : usize = MAX_ROOTLESS_PIPE_SIZE ;
21+ #[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ]
1822const BUF_SIZE : usize = 16 * 1024 ;
1923
2024#[ uucore:: main]
@@ -110,8 +114,24 @@ 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( any( target_os = "linux" , target_os = "android" ) ) ]
118+ {
119+ use rustix:: io:: write;
120+ use rustix:: pipe:: { SpliceFlags , fcntl_setpipe_size, pipe, tee} ;
121+ // fast-path for pipe. todo: port the fast-path for > file
122+ if let Ok ( ( p_read, p_write) ) = pipe ( ) {
123+ let _ = fcntl_setpipe_size ( & p_read, MAX_ROOTLESS_PIPE_SIZE ) ;
124+ let _ = fcntl_setpipe_size ( & p_write, MAX_ROOTLESS_PIPE_SIZE ) ;
125+ let _ = fcntl_setpipe_size ( & stdout, MAX_ROOTLESS_PIPE_SIZE ) ;
126+ if write ( & p_write, bytes) . is_ok ( ) {
127+ while let Ok ( 1 ..) = tee ( & p_read, & stdout, MAX_ROOTLESS_PIPE_SIZE , SpliceFlags :: MORE )
128+ {
129+ }
130+ }
131+ }
132+ }
114133
134+ let mut stdout = stdout. lock ( ) ;
115135 loop {
116136 stdout. write_all ( bytes) ?;
117137 }
@@ -122,6 +142,7 @@ mod tests {
122142 use super :: * ;
123143
124144 #[ test]
145+ #[ cfg( not( any( target_os = "linux" , target_os = "android" ) ) ) ] // Linux uses different buffer size
125146 fn test_prepare_buffer ( ) {
126147 let tests = [
127148 ( 150 , 16350 ) ,
0 commit comments