1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-02 22:17:45 +00:00

dd: reuse buffer for the most common cases

This commit is contained in:
Patrick Jackson 2022-06-07 10:45:19 -07:00 committed by Sylvestre Ledru
parent d1f7f51f99
commit 4cc058a789

View file

@ -414,6 +414,10 @@ where
let (prog_tx, rx) = mpsc::channel(); let (prog_tx, rx) = mpsc::channel();
thread::spawn(gen_prog_updater(rx, i.print_level)); 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. // The main read/write loop.
// //
// Each iteration reads blocks from the input and writes // Each iteration reads blocks from the input and writes
@ -427,7 +431,7 @@ where
// best buffer size for reading based on the number of // best buffer size for reading based on the number of
// blocks already read and the number of blocks remaining. // blocks already read and the number of blocks remaining.
let loop_bsize = calc_loop_bsize(&i.count, &rstat, &wstat, i.ibs, bsize); 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() { if rstat_update.is_empty() {
break; break;
} }
@ -600,7 +604,11 @@ impl Write for Output<io::Stdout> {
} }
/// 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. /// 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<R: Read>(i: &mut Input<R>, bsize: usize) -> std::io::Result<(ReadStat, Vec<u8>)> { fn read_helper<R: Read>(
i: &mut Input<R>,
mut buf: &mut Vec<u8>,
bsize: usize,
) -> std::io::Result<ReadStat> {
// Local Helper Fns ------------------------------------------------- // Local Helper Fns -------------------------------------------------
fn perform_swab(buf: &mut [u8]) { fn perform_swab(buf: &mut [u8]) {
for base in (1..buf.len()).step_by(2) { for base in (1..buf.len()).step_by(2) {
@ -609,14 +617,16 @@ fn read_helper<R: Read>(i: &mut Input<R>, bsize: usize) -> std::io::Result<(Read
} }
// ------------------------------------------------------------------ // ------------------------------------------------------------------
// 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 { let mut rstat = match i.cflags.sync {
Some(ch) => i.fill_blocks(&mut buf, ch)?, Some(ch) => i.fill_blocks(&mut buf, ch)?,
_ => i.fill_consecutive(&mut buf)?, _ => i.fill_consecutive(&mut buf)?,
}; };
// Return early if no data // Return early if no data
if rstat.reads_complete == 0 && rstat.reads_partial == 0 { if rstat.reads_complete == 0 && rstat.reads_partial == 0 {
return Ok((rstat, buf)); return Ok(rstat);
} }
// Perform any conv=x[,x...] options // Perform any conv=x[,x...] options
@ -626,10 +636,10 @@ fn read_helper<R: Read>(i: &mut Input<R>, bsize: usize) -> std::io::Result<(Read
match i.cflags.mode { match i.cflags.mode {
Some(ref mode) => { Some(ref mode) => {
let buf = conv_block_unblock_helper(buf, mode, &mut rstat); *buf = conv_block_unblock_helper(buf.clone(), mode, &mut rstat);
Ok((rstat, buf)) Ok(rstat)
} }
None => Ok((rstat, buf)), None => Ok(rstat),
} }
} }