stak_profiler/
lib.rs

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
//! Profiling for Stak Scheme.

extern crate alloc;

mod collapse;
mod duration;
mod error;
mod flamegraph;
mod read;
mod record;
mod reverse;
mod stack_profiler;
mod write;

pub use collapse::collapse_stacks;
pub use duration::calculate_durations;
pub use error::Error;
pub use flamegraph::calculate_flamegraph;
pub use read::read_records;
pub use record::{
    DurationRecord, ProcedureOperation, ProcedureRecord, Record, Stack, StackedRecord,
};
pub use reverse::reverse_stacks;
pub use stack_profiler::StackProfiler;
pub use write::write_records;

const COLUMN_SEPARATOR: char = '\t';
const FRAME_SEPARATOR: char = ';';

#[cfg(test)]
mod tests {
    use super::*;
    use indoc::indoc;
    use pretty_assertions::assert_eq;
    use std::io::BufReader;

    #[test]
    fn analyze_call() {
        let mut buffer = vec![];

        write_records(
            reverse_stacks(calculate_durations(read_records(BufReader::new(
                indoc!(
                    "
                    call\tfoo;bar;baz\t0
                    return\tfoo;bar;baz\t42
                    "
                )
                .trim()
                .as_bytes(),
            )))),
            &mut buffer,
        )
        .unwrap();

        assert_eq!(String::from_utf8(buffer).unwrap(), "baz;bar;foo\t42\n");
    }

    #[test]
    fn analyze_nested_calls() {
        let mut buffer = vec![];

        write_records(
            reverse_stacks(calculate_durations(read_records(BufReader::new(
                indoc!(
                    "
                    call\tbaz\t0
                    call\tbar;baz\t1
                    call\tfoo;bar;baz\t2
                    return\tfoo;bar;baz\t42
                    return\tbar;baz\t84
                    return\tbaz\t126
                    "
                )
                .trim()
                .as_bytes(),
            )))),
            &mut buffer,
        )
        .unwrap();

        assert_eq!(
            String::from_utf8(buffer).unwrap(),
            indoc!(
                "
                baz;bar;foo\t40
                baz;bar\t83
                baz\t126
                "
            )
        );
    }

    #[test]
    fn analyze_anonymous_procedure_call() {
        let mut buffer = vec![];

        write_records(
            reverse_stacks(calculate_durations(read_records(BufReader::new(
                indoc!(
                    "
                    call\t;;\t0
                    return\t;;\t42
                    "
                )
                .trim()
                .as_bytes(),
            )))),
            &mut buffer,
        )
        .unwrap();

        assert_eq!(String::from_utf8(buffer).unwrap(), ";;\t42\n");
    }
}