Coverage Report

Created: 2026-04-14 06:46

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/pprof-0.15.0/src/criterion.rs
Line
Count
Source
1
// Copyright 2020 TiKV Project Authors. Licensed under Apache-2.0.
2
3
#[cfg(feature = "flamegraph")]
4
use crate::flamegraph::Options as FlamegraphOptions;
5
#[cfg(feature = "_protobuf")]
6
use crate::protos::Message;
7
8
use crate::ProfilerGuard;
9
use criterion::profiler::Profiler;
10
11
use std::fs::File;
12
#[cfg(feature = "_protobuf")]
13
use std::io::Write;
14
use std::marker::PhantomData;
15
use std::os::raw::c_int;
16
use std::path::Path;
17
18
#[allow(clippy::large_enum_variant)]
19
pub enum Output<'a> {
20
    #[cfg(feature = "flamegraph")]
21
    Flamegraph(Option<FlamegraphOptions<'a>>),
22
23
    #[cfg(feature = "_protobuf")]
24
    Protobuf,
25
26
    #[deprecated(
27
        note = "This branch is used to include lifetime parameter. Don't use it directly."
28
    )]
29
    _Phantom(PhantomData<&'a ()>),
30
}
31
32
pub struct PProfProfiler<'a, 'b> {
33
    frequency: c_int,
34
    output: Output<'b>,
35
    active_profiler: Option<ProfilerGuard<'a>>,
36
}
37
38
impl<'a, 'b> PProfProfiler<'a, 'b> {
39
0
    pub fn new(frequency: c_int, output: Output<'b>) -> Self {
40
0
        Self {
41
0
            frequency,
42
0
            output,
43
0
            active_profiler: None,
44
0
        }
45
0
    }
46
}
47
48
#[cfg(not(any(feature = "_protobuf", feature = "flamegraph")))]
49
compile_error!("Either feature \"protobuf\" or \"flamegraph\" must be enabled when \"criterion\" feature is enabled.");
50
51
impl<'a, 'b> Profiler for PProfProfiler<'a, 'b> {
52
0
    fn start_profiling(&mut self, _benchmark_id: &str, _benchmark_dir: &Path) {
53
0
        self.active_profiler = Some(ProfilerGuard::new(self.frequency).unwrap());
54
0
    }
55
56
0
    fn stop_profiling(&mut self, _benchmark_id: &str, benchmark_dir: &Path) {
57
0
        std::fs::create_dir_all(benchmark_dir).unwrap();
58
59
0
        let filename = match self.output {
60
            #[cfg(feature = "flamegraph")]
61
            Output::Flamegraph(_) => "flamegraph.svg",
62
            #[cfg(feature = "_protobuf")]
63
0
            Output::Protobuf => "profile.pb",
64
            // This is `""` but not `unreachable!()`, because `unreachable!()`
65
            // will result in another compile error, so that the user may not
66
            // realize the error thrown by `compile_error!()` at the first time.
67
0
            _ => "",
68
        };
69
0
        let output_path = benchmark_dir.join(filename);
70
0
        let output_file = File::create(&output_path).unwrap_or_else(|_| {
71
0
            panic!("File system error while creating {}", output_path.display())
72
        });
73
74
0
        if let Some(profiler) = self.active_profiler.take() {
75
0
            match &mut self.output {
76
                #[cfg(feature = "flamegraph")]
77
                Output::Flamegraph(options) => {
78
                    let default_options = &mut FlamegraphOptions::default();
79
                    let options = options.as_mut().unwrap_or(default_options);
80
81
                    profiler
82
                        .report()
83
                        .build()
84
                        .unwrap()
85
                        .flamegraph_with_options(output_file, options)
86
                        .expect("Error while writing flamegraph");
87
                }
88
89
                #[cfg(feature = "_protobuf")]
90
0
                Output::Protobuf => {
91
0
                    let mut output_file = output_file;
92
0
93
0
                    let profile = profiler.report().build().unwrap().pprof().unwrap();
94
0
95
0
                    let mut content = Vec::new();
96
0
                    #[cfg(not(feature = "protobuf-codec"))]
97
0
                    profile
98
0
                        .encode(&mut content)
99
0
                        .expect("Error while encoding protobuf");
100
0
                    #[cfg(feature = "protobuf-codec")]
101
0
                    profile
102
0
                        .write_to_vec(&mut content)
103
0
                        .expect("Error while encoding protobuf");
104
0
105
0
                    output_file
106
0
                        .write_all(&content)
107
0
                        .expect("Error while writing protobuf");
108
0
                }
109
110
0
                _ => unreachable!(),
111
            }
112
0
        }
113
0
    }
114
}