File: add.rs

package info (click to toggle)
rust-rust-unixfs 0.4.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 652 kB
  • sloc: sh: 17; makefile: 2
file content (153 lines) | stat: -rw-r--r-- 3,651 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
use cid::Cid;
use rust_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(0x70, 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;
        }
    }
}