2020-07-03 12:20:58 +03:00

154 lines
3.6 KiB
Rust

use cid::Cid;
use ipfs_unixfs::file::adder::FileAdder;
use std::fmt;
use std::io::{BufRead, BufReader};
use std::time::Duration;
fn main() {
// read stdin, maybe produce stdout car?
let stdin = std::io::stdin();
let stdin = stdin.lock();
let mut adder = FileAdder::default();
let mut stdin = BufReader::with_capacity(adder.size_hint(), stdin);
let mut stats = Stats::default();
let mut input = 0;
let start = std::time::Instant::now();
loop {
match stdin.fill_buf().unwrap() {
x if x.is_empty() => {
eprintln!("finishing");
eprintln!("{:?}", adder);
let blocks = adder.finish();
stats.process(blocks);
break;
}
x => {
let mut total = 0;
while total < x.len() {
let (blocks, consumed) = adder.push(&x[total..]);
stats.process(blocks);
input += consumed;
total += consumed;
}
assert_eq!(total, x.len());
stdin.consume(total);
}
}
}
let process_stats = get_process_stats();
eprintln!("{}", stats);
let total = start.elapsed();
if let Some(process_stats) = process_stats {
eprint!("{}, ", process_stats);
}
eprintln!("total: {:?}", total);
let megabytes = 1024.0 * 1024.0;
eprintln!(
"Input: {:.2} MB/s (read {} bytes)",
(input as f64 / megabytes) / total.as_secs_f64(),
input
);
eprintln!(
"Output: {:.2} MB/s",
(stats.block_bytes as f64 / megabytes) / total.as_secs_f64()
);
}
struct ProcessStats {
user_time: Duration,
system_time: Duration,
max_rss: i64,
}
impl fmt::Display for ProcessStats {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(
fmt,
"Max RSS: {} KB, utime: {:?}, stime: {:?}",
self.max_rss, self.user_time, self.system_time
)
}
}
#[cfg(unix)]
fn get_process_stats() -> Option<ProcessStats> {
fn to_duration(tv: libc::timeval) -> Duration {
assert!(tv.tv_sec >= 0);
Duration::new(tv.tv_sec as u64, tv.tv_usec as u32)
}
let (max_rss, user_time, system_time) = unsafe {
let mut rusage: libc::rusage = std::mem::zeroed();
let retval = libc::getrusage(libc::RUSAGE_SELF, &mut rusage as *mut _);
assert_eq!(retval, 0);
(rusage.ru_maxrss, rusage.ru_utime, rusage.ru_stime)
};
let user_time = to_duration(user_time);
let system_time = to_duration(system_time);
Some(ProcessStats {
user_time,
system_time,
max_rss,
})
}
#[cfg(not(unix))]
fn get_process_stats() -> Option<ProcessStats> {
None
}
#[derive(Default)]
struct Stats {
blocks: usize,
block_bytes: u64,
last: Option<Cid>,
}
impl fmt::Display for Stats {
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
let hash = self.last.as_ref().unwrap().hash();
let cidv1 = Cid::new_v1(cid::Codec::DagProtobuf, hash.to_owned());
write!(
fmt,
"{} blocks, {} block bytes, {} or {}",
self.blocks,
self.block_bytes,
self.last.as_ref().unwrap(),
cidv1,
)
}
}
impl Stats {
fn process<I: Iterator<Item = (Cid, Vec<u8>)>>(&mut self, new_blocks: I) {
for (cid, block) in new_blocks {
self.last = Some(cid);
self.blocks += 1;
self.block_bytes += block.len() as u64;
}
}
}