diff --git a/Cargo.toml b/Cargo.toml index a4c4ef0..7a3cfa0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rng" -version = "0.2.0" +version = "0.2.1" authors = ["Avril "] edition = "2018" @@ -14,3 +14,9 @@ panic = "unwind" [dependencies] getrandom = "0.1" + +[features] +# Dynamically allocate and populate all memory needed for `--bytes` at runtime instead of streaming in fixed size blocks. +# +# This can slightly improve total performance for large outputs, at the cost of a proportionally, arbitrary sized memory allocation along with a proportionally increasing wait while the entire area is populated. +bytes-dynamic = [] \ No newline at end of file diff --git a/src/main.rs b/src/main.rs index 90a3f56..f14669a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,6 +7,8 @@ use getrandom::*; mod parse; mod r#impl; +const BYTES_BUFFER_SIZE: usize = 4096; + fn get() -> Result { let mut value: T = Default::default(); @@ -151,22 +153,40 @@ fn shuffle(args: &[String]) -> Result<(), Error> fn bytes(args: &[String]) -> Result<(), Error> { if args.len() < 1 { - usage(); + usage(); } else { let num = parse::bytes(&args[0]).expect("Failed to parse number of bytes") as usize; - let mut mem = Vec::with_capacity(num); - - debug_assert_eq!(mem.capacity(), num); - // SAFETY: populating uninitialised memory with random data. There are no reads to the uninitialised data. - unsafe { - mem.set_len(num); - populate(&mut mem[..])?; + + if cfg!(feature="bytes-dynamic") { + let mut mem = Vec::with_capacity(num); + + debug_assert_eq!(mem.capacity(), num); + // SAFETY: populating uninitialised memory with random data. There are no reads to the uninitialised data. + unsafe { + mem.set_len(num); + populate(&mut mem[..])?; + } + debug_assert_eq!(num, mem.len()); + + let stdout = std::io::stdout(); + + use std::io::Write; + stdout.lock().write_all(&mem[..]).expect("write error"); + } else { + let mut buffer = [0u8; BYTES_BUFFER_SIZE]; + let mut num = num; + let stdout = std::io::stdout(); + let mut stdout = stdout.lock(); + + while num > 0 { + let w = std::cmp::min(num, BYTES_BUFFER_SIZE); + getrandom(&mut buffer[..w])?; + + use std::io::Write; + stdout.write_all(&buffer[..w]).expect("write error"); + num -= w; + } } - debug_assert_eq!(num, mem.len()); - - let stdout = std::io::stdout(); - use std::io::Write; - stdout.lock().write_all(&mem[..]).expect("write error"); } Ok(()) }