Skip to main content

profile_inspect/types/
cpu.rs

1use serde::Deserialize;
2
3/// Raw V8 CPU profile as produced by Chrome DevTools / Node.js
4#[derive(Debug, Deserialize)]
5#[serde(rename_all = "camelCase")]
6pub struct CpuProfile {
7    /// Array of profile nodes (call frames with timing data)
8    pub nodes: Vec<CpuProfileNode>,
9
10    /// Timestamps of samples in microseconds
11    #[serde(default)]
12    pub samples: Vec<u32>,
13
14    /// Time deltas between samples in microseconds
15    #[serde(default)]
16    pub time_deltas: Vec<i64>,
17
18    /// Profile start time in microseconds
19    pub start_time: u64,
20
21    /// Profile end time in microseconds
22    pub end_time: u64,
23}
24
25/// A single node in the CPU profile call tree
26#[derive(Debug, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct CpuProfileNode {
29    /// Unique node identifier
30    pub id: u32,
31
32    /// Call frame information
33    pub call_frame: CallFrame,
34
35    /// Child node IDs
36    #[serde(default)]
37    pub children: Vec<u32>,
38
39    /// Hit count (number of samples where this was the leaf)
40    #[serde(default)]
41    pub hit_count: u32,
42
43    /// Position ticks (line-level timing data)
44    #[serde(default)]
45    pub position_ticks: Vec<PositionTickInfo>,
46}
47
48/// Call frame information for a profile node
49#[derive(Debug, Deserialize)]
50#[serde(rename_all = "camelCase")]
51pub struct CallFrame {
52    /// Function name
53    pub function_name: String,
54
55    /// Script ID
56    #[serde(default)]
57    pub script_id: String,
58
59    /// Script URL (file path or URL)
60    #[serde(default)]
61    pub url: String,
62
63    /// Line number (0-based)
64    #[serde(default)]
65    pub line_number: i32,
66
67    /// Column number (0-based)
68    #[serde(default)]
69    pub column_number: i32,
70}
71
72/// Position tick information for line-level profiling
73#[derive(Debug, Deserialize)]
74#[serde(rename_all = "camelCase")]
75pub struct PositionTickInfo {
76    /// Line number
77    pub line: u32,
78
79    /// Number of ticks at this line
80    pub ticks: u32,
81}
82
83impl CpuProfile {
84    /// Parse a CPU profile from JSON
85    ///
86    /// # Errors
87    /// Returns an error if the JSON is invalid.
88    pub fn from_json(json: &str) -> Result<Self, serde_json::Error> {
89        serde_json::from_str(json)
90    }
91
92    /// Get the total duration in microseconds
93    pub fn duration_us(&self) -> u64 {
94        self.end_time.saturating_sub(self.start_time)
95    }
96
97    /// Get the total duration in milliseconds
98    #[expect(clippy::cast_precision_loss)]
99    pub fn duration_ms(&self) -> f64 {
100        self.duration_us() as f64 / 1000.0
101    }
102}