@@ -24,32 +24,43 @@ pub(super) fn write_fast_using_splice<R: FdReadable, S: AsRawFd + AsFd>(
2424 write_fd : & S ,
2525) -> CatResult < bool > {
2626 use nix:: fcntl:: { FcntlArg , fcntl} ;
27- 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- ) ;
33-
34- loop {
35- match splice ( & handle. reader , & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
36- Ok ( n) => {
37- if n == 0 {
38- return Ok ( false ) ;
27+ const FIRST_PIPE_SIZE : usize = 64 * 1024 ;
28+ if splice ( & handle. reader , & write_fd, FIRST_PIPE_SIZE ) . is_ok ( ) {
29+ // fcntl improves performance for large file which is large overhead for small files
30+ let _ = fcntl (
31+ write_fd,
32+ FcntlArg :: F_SETPIPE_SZ ( MAX_ROOTLESS_PIPE_SIZE as i32 ) ,
33+ ) ;
34+ loop {
35+ match splice ( & handle. reader , & write_fd, MAX_ROOTLESS_PIPE_SIZE ) {
36+ Ok ( 1 ..) => { }
37+ Ok ( 0 ) => return Ok ( false ) ,
38+ Err ( _) => return Ok ( true ) ,
39+ }
40+ }
41+ } else {
42+ // output is not pipe. Needs broker to use splice() which is high cost for small files
43+ let ( pipe_rd, pipe_wr) = pipe ( ) ?;
44+ loop {
45+ match splice ( & handle. reader , & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
46+ Ok ( n) => {
47+ if n == 0 {
48+ return Ok ( false ) ;
49+ }
50+ if splice_exact ( & pipe_rd, write_fd, n) . is_err ( ) {
51+ // If the first splice manages to copy to the intermediate
52+ // pipe, but the second splice to stdout fails for some reason
53+ // we can recover by copying the data that we have from the
54+ // intermediate pipe to stdout using normal read/write. Then
55+ // we tell the caller to fall back.
56+ copy_exact ( & pipe_rd, write_fd, n) ?;
57+ return Ok ( true ) ;
58+ }
3959 }
40- if splice_exact ( & pipe_rd, write_fd, n) . is_err ( ) {
41- // If the first splice manages to copy to the intermediate
42- // pipe, but the second splice to stdout fails for some reason
43- // we can recover by copying the data that we have from the
44- // intermediate pipe to stdout using normal read/write. Then
45- // we tell the caller to fall back.
46- copy_exact ( & pipe_rd, write_fd, n) ?;
60+ Err ( _) => {
4761 return Ok ( true ) ;
4862 }
4963 }
50- Err ( _) => {
51- return Ok ( true ) ;
52- }
5364 }
5465 }
5566}
0 commit comments