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
extern crate ndarray;

use std::fmt;
use profiler::Profiler;
use self::ndarray::Axis;

// pretty-print separator of functions
static DASHES: &'static str = "-----------------------------------------------------------------------";

/// Format a number with thousands separators. copied from cargo bench.
fn fmt_thousands_sep(n: f64, sep: char) -> String {
    let mut n_usize = n as usize;
    use std::fmt::Write;
    let mut output = String::new();
    let mut trailing = false;
    for &pow in &[9, 6, 3, 0] {
        let base = 10_usize.pow(pow);
        if pow == 0 || trailing || n_usize / base != 0 {
            if !trailing {
                output.write_fmt(format_args!("{}", n_usize / base)).unwrap();
            } else {
                output.write_fmt(format_args!("{:03}", n_usize / base)).unwrap();
            }
            if pow != 0 {
                output.push(sep);
            }
            trailing = true;
        }

        n_usize %= base;
    }

    output
}

/// Pretty-print the profiler outputs into user-friendly formats.
impl fmt::Display for Profiler {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match *self {
            Profiler::CacheGrind { ref ir,
                                   ref i1mr,
                                   ref ilmr,
                                   ref dr,
                                   ref d1mr,
                                   ref dlmr,
                                   ref dw,
                                   ref d1mw,
                                   ref dlmw,
                                   ref data,
                                   ref functs } => {
                let _ = write!(f,
                       "\n\x1b[32mTotal Memory Accesses\x1b[0m...{}\t\x1b[0m\n\
                       \n\x1b[32mTotal L1 I-Cache Misses\x1b[0m...{} ({}%)\t\x1b[0m\
                       \n\x1b[32mTotal LL I-Cache Misses\x1b[0m...{} ({}%)\t\x1b[0m\
                       \n\x1b[32mTotal L1 D-Cache Misses\x1b[0m...{} ({}%)\t\x1b[0m\
                        \n\x1b[32mTotal LL D-Cache Misses\x1b[0m...{} ({}%)\t\x1b[0m\n\n\

                    ",

                       fmt_thousands_sep((ir + dr + dw), ','),
                       fmt_thousands_sep(*i1mr, ','),
                       fmt_thousands_sep(i1mr / (ir + dr + dw) * 100., ','),
                       fmt_thousands_sep(*ilmr, ','),
                       fmt_thousands_sep(ilmr / (ir + dr + dw) * 100., ','),
                       fmt_thousands_sep(d1mr + d1mw, ','),
                       fmt_thousands_sep((d1mr + d1mw) / (ir + dr + dw) * 100., ','),
                       fmt_thousands_sep(dlmr + dlmw, ','),
                       fmt_thousands_sep((dlmr + dlmw) / (ir + dr + dw) * 100., ','),
                );
                let _ = write!(f,
                               " \x1b[1;36mIr  \x1b[1;36mI1mr \x1b[1;36mILmr  \x1b[1;36mDr  \
                                \x1b[1;36mD1mr \x1b[1;36mDLmr  \x1b[1;36mDw  \x1b[1;36mD1mw \
                                \x1b[1;36mDLmw\n");

                for (ref x, y) in data.axis_iter(Axis(0)).zip(functs.iter()) {
                    let _ = write!(f,
                                   "\x1b[0m{:.2} {:.2} {:.2} {:.2} {:.2} {:.2} {:.2} {:.2} {:.2} \
                                    {}\n",
                                   x[0] / ir,
                                   x[1] / i1mr,
                                   x[2] / ilmr,
                                   x[3] / dr,
                                   x[4] / d1mr,
                                   x[5] / dlmr,
                                   x[6] / dw,
                                   x[7] / d1mw,
                                   x[8] / dlmw,
                                   y);
                    println!("{}", DASHES);
                }
                Ok(())
            }

            Profiler::CallGrind { ref total_instructions, ref instructions, ref functs } => {

                let _ = write!(f,
                               "\n\x1b[32mTotal Instructions\x1b[0m...{}\n\n\x1b[0m",
                               fmt_thousands_sep(*total_instructions, ','));

                for (&x, ref y) in instructions.iter().zip(functs.iter()) {
                    {

                        let perc = x / total_instructions * 100.;
                        match perc {
                            t if t >= 50.0 => {
                                let _ = write!(f,
                                               "{} (\x1b[31m{:.1}%\x1b[0m)\x1b[0m {}\n",
                                               fmt_thousands_sep(x, ','),
                                               t,
                                               y);
                                println!("{}", DASHES);
                            }
                            t if (t >= 30.0) & (t < 50.0) => {
                                let _ = write!(f,
                                               "{} (\x1b[33m{:.1}%\x1b[0m)\x1b[0m {}\n",
                                               fmt_thousands_sep(x, ','),
                                               t,
                                               y);
                                println!("{}", DASHES);
                            }
                            _ => {
                                let _ = write!(f,
                                               "{} (\x1b[32m{:.1}%\x1b[0m)\x1b[0m {}\n",
                                               fmt_thousands_sep(x, ','),
                                               x / total_instructions * 100.,
                                               y);
                                println!("{}", DASHES);
                            }
                        }
                    }
                }
                Ok(())

            }

        }
    }
}


#[cfg(test)]
mod test {
    #[test]
    fn test_fmt_thousands_sep() {
        assert_eq!(1, 1);
    }

}