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
#[macro_use]
extern crate serde;
pub mod model;
use flame::Span;
use indexmap::IndexSet;
use model::*;
use std::io::Write;
const JSON_SCHEMA_URL: &str = "https://www.speedscope.app/file-format-schema.json";
pub fn spans_to_speedscope(spans: Vec<Span>) -> SpeedscopeFile {
let mut frames = IndexSet::new();
let profiles = spans
.into_iter()
.map(|span| Profile::Evented {
name: span.name.clone(),
unit: ValueUnit::Nanoseconds,
start_value: span.start_ns,
end_value: span.end_ns,
events: {
let mut events = Vec::new();
span_extend_events(&mut frames, &mut events, span);
events
},
})
.collect();
SpeedscopeFile {
schema: JSON_SCHEMA_URL,
active_profile_index: None,
exporter: None,
name: None,
profiles,
shared: Shared {
frames: frames.into_iter().collect(),
},
}
}
fn span_extend_events(frames: &mut IndexSet<Frame>, events: &mut Vec<Event>, span: Span) {
let (frame, _) = frames.insert_full(Frame::new(span.name));
events.push(Event {
event_type: EventType::OpenFrame,
at: span.start_ns,
frame,
});
for child in span.children {
span_extend_events(frames, events, child);
}
events.push(Event {
event_type: EventType::CloseFrame,
at: span.end_ns,
frame,
});
}
#[inline]
pub fn dump(writer: impl Write) -> serde_json::Result<()> {
write_spans(writer, flame::spans())
}
#[inline]
pub fn write_spans(writer: impl Write, spans: Vec<Span>) -> serde_json::Result<()> {
let speedscope = spans_to_speedscope(spans);
serde_json::to_writer(writer, &speedscope)
}