1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-08-02 05:57:46 +00:00

Implements internal read/write buffer optimization

- Spoiler Alert: Turns out it was just the lcm.
This commit is contained in:
Tyler 2021-06-08 14:14:19 -07:00
parent ef6c850833
commit 96fd665ce1
4 changed files with 1093 additions and 1082 deletions

2057
Cargo.lock generated

File diff suppressed because it is too large Load diff

View file

@ -19,11 +19,11 @@ uucore = { version=">=0.0.7", package="uucore", path="../../uucore" }
uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" } uucore_procs = { version=">=0.0.5", package="uucore_procs", path="../../uucore_procs" }
# Probably best to keep this identical to the version of getopts in the uucore crate # Probably best to keep this identical to the version of getopts in the uucore crate
getopts = "<= 0.2.21" getopts = "<= 0.2.21"
gcd = "2.0"
[dev-dependencies] [dev-dependencies]
md-5 = "0.9" md-5 = "0.9"
hex-literal = "0.3" hex-literal = "0.3"
rand = "0.8"
[[bin]] [[bin]]
name = "dd" name = "dd"

View file

@ -18,6 +18,7 @@ mod parseargs;
mod conversion_tables; mod conversion_tables;
use conversion_tables::*; use conversion_tables::*;
use gcd::Gcd;
use std::cmp; use std::cmp;
use std::convert::TryInto; use std::convert::TryInto;
use std::error::Error; use std::error::Error;
@ -783,21 +784,6 @@ fn read_helper<R: Read, W: Write>(i: &mut Input<R>, o: &mut Output<W>, bsize: us
} }
} }
/// Write obs-size blocks
// fn write_helper<W: Write>(o: &mut Output<W>, buf: Vec<u8>) -> Result<usize, Box<dyn Error>>
// {
// let mut base_idx = 0;
//
// while base_idx < buf.len()
// {
// let width = cmp::min(base_idx+o.obs, buf.len());
// let wlen = o.write(&mut buf[base_idx..width])?;
// base_idx += wlen;
// }
//
// Ok(base_idx)
// }
/// Generate a progress updater that tracks progress, receives updates, and TODO: responds to signals. /// Generate a progress updater that tracks progress, receives updates, and TODO: responds to signals.
fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> () fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> ()
{ {
@ -822,11 +808,13 @@ fn gen_prog_updater(rx: mpsc::Receiver<usize>) -> impl Fn() -> ()
} }
} }
/// Find the greatest common factor for the pair of integers. #[inline]
fn gcf(u: usize, v: usize) -> usize fn calc_bsize(ibs: usize, obs: usize) -> usize
{ {
// TODO: 1 is not the gcf of all pairs of integers... let gcd = Gcd::gcd(ibs, obs);
1 let lcm = (ibs*obs)/gcd;
lcm
} }
/// Perform the copy/convert opertaions. Stdout version /// Perform the copy/convert opertaions. Stdout version
@ -836,8 +824,7 @@ fn dd_stdout<R: Read>(mut i: Input<R>, mut o: Output<io::Stdout>) -> Result<(usi
{ {
let mut bytes_in = 0; let mut bytes_in = 0;
let mut bytes_out = 0; let mut bytes_out = 0;
let gcf = gcf(i.ibs, o.obs); let bsize = calc_bsize(i.ibs, o.obs);
let buf_size = (i.ibs/gcf)*(o.obs/gcf);
let prog_tx = if i.xfer_stats == StatusLevel::Progress let prog_tx = if i.xfer_stats == StatusLevel::Progress
{ {
@ -852,7 +839,7 @@ fn dd_stdout<R: Read>(mut i: Input<R>, mut o: Output<io::Stdout>) -> Result<(usi
loop loop
{ {
match read_helper(&mut i, &mut o, buf_size)? match read_helper(&mut i, &mut o, bsize)?
{ {
(0, _) => (0, _) =>
break, break,
@ -891,8 +878,7 @@ fn dd_fileout<R: Read>(mut i: Input<R>, mut o: Output<File>) -> Result<(usize, u
{ {
let mut bytes_in = 0; let mut bytes_in = 0;
let mut bytes_out = 0; let mut bytes_out = 0;
let gcf = gcf(i.ibs, o.obs); let bsize = calc_bsize(i.ibs, o.obs);
let buf_size = (i.ibs/gcf)*(o.obs/gcf);
let prog_tx = if i.xfer_stats == StatusLevel::Progress let prog_tx = if i.xfer_stats == StatusLevel::Progress
{ {
@ -907,13 +893,13 @@ fn dd_fileout<R: Read>(mut i: Input<R>, mut o: Output<File>) -> Result<(usize, u
loop loop
{ {
match read_helper(&mut i, &mut o, buf_size)? match read_helper(&mut i, &mut o, bsize)?
{ {
(0, _) => (0, _) =>
break, break,
(rlen, buf) => (rlen, buf) =>
{ {
let wlen = o.write(&buf)?; let wlen = o.write_blocks(buf)?;
bytes_in += rlen; bytes_in += rlen;
bytes_out += wlen; bytes_out += wlen;

View file

@ -65,3 +65,81 @@ make_spec_test!(
File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(), File::open("./test-resources/random-5828891cb1230748e146f34223bbd3b5.test").unwrap(),
format!("./test-resources/FAILED-{}.test", "random-73k-obs-lt-not-a-multiple-ibs") format!("./test-resources/FAILED-{}.test", "random-73k-obs-lt-not-a-multiple-ibs")
); );
// Test internal buffer size fn
#[test]
fn bsize_test_primes()
{
let (n,m) = (7901, 7919);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, n*m);
}
#[test]
fn bsize_test_rel_prime_obs_greater()
{
let (n,m) = (7*5119, 13*5119);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, 7*13*5119);
}
#[test]
fn bsize_test_rel_prime_ibs_greater()
{
let (n,m) = (13*5119, 7*5119);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, 7*13*5119);
}
#[test]
fn bsize_test_3fac_rel_prime()
{
let (n,m) = (11*13*5119, 7*11*5119);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, 7*11*13*5119);
}
#[test]
fn bsize_test_ibs_greater()
{
let (n,m) = (512*1024, 256*1024);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, n);
}
#[test]
fn bsize_test_obs_greater()
{
let (n,m) = (256*1024, 512*1024);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, m);
}
#[test]
fn bsize_test_bs_eq()
{
let (n,m) = (1024, 1024);
let res = calc_bsize(n, m);
assert!(res % n == 0);
assert!(res % m == 0);
assert_eq!(res, m);
}