Created
October 8, 2019 21:32
-
-
Save BartMassey/44dcd90e828fe0830599c8f229291069 to your computer and use it in GitHub Desktop.
Good Appender, not Great
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // https://www.reddit.com/r/rust/comments/df12bs/roast_my_code_greatappender_repeatedly_append/ | |
| use std::convert::TryInto; | |
| use std::fs::OpenOptions; | |
| use std::io::Write; | |
| use std::sync::atomic::{AtomicBool, Ordering}; | |
| use std::sync::Arc; | |
| /// good-appender | |
| fn main() { | |
| let args: Vec<String> = std::env::args().collect(); | |
| let nargs = args.len(); | |
| assert!(nargs >= 2); | |
| let filename = &*args[1]; | |
| let repeated_str = if nargs >= 3 { | |
| &*args[2] | |
| } else { | |
| "message" | |
| }; | |
| let per_write = if nargs >= 4 { | |
| args[3].parse().expect("per_write should be numeric") | |
| } else { | |
| 1024_usize | |
| }; | |
| let mut file = OpenOptions::new() | |
| .append(true) | |
| .create(true) | |
| .open(filename) | |
| .expect("Could not open nor create file"); | |
| let should_stop = Arc::new(AtomicBool::new(false)); | |
| signal_hook::flag::register(signal_hook::SIGINT, Arc::clone(&should_stop)) | |
| .expect("Could not register SIGINT handler"); | |
| let buf = make_buffer(repeated_str, per_write); | |
| let mut bytes = 0; | |
| let start_time = std::time::Instant::now(); | |
| while !should_stop.load(Ordering::Relaxed) { | |
| bytes += file.write(&buf).expect("Could not write"); | |
| } | |
| let now = std::time::Instant::now(); | |
| let elapsed = now.duration_since(start_time).as_secs(); | |
| let average_throughput = bytes as f64 / elapsed as f64; | |
| let atpb: u64 = average_throughput as u64; | |
| let bytes: u64 = bytes.try_into().expect("too many bytes"); | |
| eprintln!( | |
| "\rWritten {}\t{:.3e} B/s ({}/s)", | |
| bytefmt::format(bytes), | |
| average_throughput, | |
| bytefmt::format(atpb), | |
| ); | |
| } | |
| fn make_buffer(message: &str, per_write: usize) -> Vec<u8> { | |
| let message = message.to_string() + "\n"; | |
| let message = message.as_bytes(); | |
| let nmessage = message.len(); | |
| let mut buf = Vec::new(); | |
| let mut bytes_in_buf = 0; | |
| while bytes_in_buf < per_write { | |
| buf.extend_from_slice(message); | |
| bytes_in_buf += nmessage; | |
| } | |
| buf | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment