From 4cc058a78903252cdf1eec3c11e735f158b176f7 Mon Sep 17 00:00:00 2001 From: Patrick Jackson Date: Tue, 7 Jun 2022 10:45:19 -0700 Subject: [PATCH] dd: reuse buffer for the most common cases --- src/uu/dd/src/dd.rs | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/src/uu/dd/src/dd.rs b/src/uu/dd/src/dd.rs index 115da8bcc..46c35d0ec 100644 --- a/src/uu/dd/src/dd.rs +++ b/src/uu/dd/src/dd.rs @@ -414,6 +414,10 @@ where let (prog_tx, rx) = mpsc::channel(); thread::spawn(gen_prog_updater(rx, i.print_level)); + // Create a common buffer with a capacity of the block size. + // This is the max size needed. + let mut buf = vec![BUF_INIT_BYTE; bsize]; + // The main read/write loop. // // Each iteration reads blocks from the input and writes @@ -427,7 +431,7 @@ where // best buffer size for reading based on the number of // blocks already read and the number of blocks remaining. let loop_bsize = calc_loop_bsize(&i.count, &rstat, &wstat, i.ibs, bsize); - let (rstat_update, buf) = read_helper(&mut i, loop_bsize)?; + let rstat_update = read_helper(&mut i, &mut buf, loop_bsize)?; if rstat_update.is_empty() { break; } @@ -600,7 +604,11 @@ impl Write for Output { } /// Read helper performs read operations common to all dd reads, and dispatches the buffer to relevant helper functions as dictated by the operations requested by the user. -fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(ReadStat, Vec)> { +fn read_helper( + i: &mut Input, + mut buf: &mut Vec, + bsize: usize, +) -> std::io::Result { // Local Helper Fns ------------------------------------------------- fn perform_swab(buf: &mut [u8]) { for base in (1..buf.len()).step_by(2) { @@ -609,14 +617,16 @@ fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(Read } // ------------------------------------------------------------------ // Read - let mut buf = vec![BUF_INIT_BYTE; bsize]; + // Resize the buffer to the bsize. Any garbage data in the buffer is overwritten or truncated, so there is no need to fill with BUF_INIT_BYTE first. + buf.resize(bsize, BUF_INIT_BYTE); + let mut rstat = match i.cflags.sync { Some(ch) => i.fill_blocks(&mut buf, ch)?, _ => i.fill_consecutive(&mut buf)?, }; // Return early if no data if rstat.reads_complete == 0 && rstat.reads_partial == 0 { - return Ok((rstat, buf)); + return Ok(rstat); } // Perform any conv=x[,x...] options @@ -626,10 +636,10 @@ fn read_helper(i: &mut Input, bsize: usize) -> std::io::Result<(Read match i.cflags.mode { Some(ref mode) => { - let buf = conv_block_unblock_helper(buf, mode, &mut rstat); - Ok((rstat, buf)) + *buf = conv_block_unblock_helper(buf.clone(), mode, &mut rstat); + Ok(rstat) } - None => Ok((rstat, buf)), + None => Ok(rstat), } }