@@ -40,24 +40,33 @@ const BUF_SIZE: usize = 64 * 1024;
4040#[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
4141fn count_bytes_using_splice ( fd : & impl AsFd ) -> Result < usize , usize > {
4242 let null_file = uucore:: pipes:: dev_null ( ) . ok_or ( 0_usize ) ?;
43- // todo: avoid generating broker if input is pipe (fcntl_setpipe_size succeed) and directly splice() to /dev/null to save RAM usage
44- let ( pipe_rd, pipe_wr) = pipe ( ) . map_err ( |_| 0_usize ) ?;
45-
4643 let mut byte_count = 0 ;
47- // improve throughput from pipe
48- let _ = rustix:: pipe:: fcntl_setpipe_size ( fd, MAX_ROOTLESS_PIPE_SIZE ) ;
49- loop {
50- match splice ( fd, & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
51- Ok ( 0 ) => break ,
52- Ok ( res) => {
53- byte_count += res;
54- // Silent the warning as we want to the error message
55- if splice_exact ( & pipe_rd, & null_file, res) . is_err ( ) {
56- return Err ( byte_count) ;
44+ if let Ok ( res) = splice ( fd, & null_file, MAX_ROOTLESS_PIPE_SIZE ) {
45+ byte_count += res;
46+ // no need to increase pipe size of input fd since
47+ // - sender with splice probably increased size already
48+ // - sender without splice is bottleneck of our wc -c
49+ loop {
50+ match splice ( fd, & null_file, MAX_ROOTLESS_PIPE_SIZE ) {
51+ Ok ( 0 ) => break ,
52+ Ok ( res) => byte_count += res,
53+ Err ( _) => return Err ( byte_count) ,
54+ }
55+ }
56+ } else if let Ok ( ( pipe_rd, pipe_wr) ) = pipe ( ) {
57+ // input is not pipe. needs broker to use splice() with additional cost
58+ loop {
59+ match splice ( fd, & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
60+ Ok ( 0 ) => break ,
61+ Ok ( res) => {
62+ byte_count += res;
63+ splice_exact ( & pipe_rd, & null_file, res) . map_err ( |_| byte_count) ?;
5764 }
65+ Err ( _) => return Err ( byte_count) ,
5866 }
59- Err ( _) => return Err ( byte_count) ,
6067 }
68+ } else {
69+ return Ok ( 0_usize ) ;
6170 }
6271
6372 Ok ( byte_count)
0 commit comments