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
//! The idea of firestorm-core  was to try to make a small API subset so that multiple
//! versions of firestorm with the potential for backward incompatable API changes
//! between them could share common data so that profiling all dependencies would
//! still work. This probably fell short, but it's a step toward that.
// TODO: The main problem about the above is that multiple dependencies would not be enabled.
// So, even the enable/disable re-export paradigm has to come from this crate.

use std::cell::UnsafeCell;

// The TimeSample type exists to make time opaque for backward compatability.
// The means by which time is sampled has a huge impact on the performance of this
// crate. So, it is desirable to be able to change the method without requiring
// a version bump.
//
// We also make the method configurable

#[cfg(feature = "cpu_time")]
mod cpu_time;
#[cfg(feature = "cpu_time")]
pub use cpu_time::*;

#[cfg(feature = "system_time")]
mod system_time;
#[cfg(feature = "system_time")]
pub use system_time::*;

#[cfg(not(any(feature = "system_time", feature = "cpu_time")))]
mod disabled;
#[cfg(not(any(feature = "system_time", feature = "cpu_time")))]
pub use disabled::*;

type Str = &'static &'static str;

// TODO: Add Pause, Resume to help with things like the
// amortized cost of expanding the length of the events
// array getting reported as a part of another operation.
#[non_exhaustive]
pub enum Start {
    Method { typ: &'static str, signature: Str },
    Func { signature: Str },
    Section { name: Str },
}

/// A lazy string format.
#[non_exhaustive]
pub enum EventData {
    Start(Start),
    End,
}

/// A tiny record of a method call which when played back can construct
/// a profiling state. Several representations were considered, the most
/// elaborate of which would write variable length data to the event stream.
/// Ideally, data would be an &'static EventData to avoid writing more data
/// than is necessary but limitations in the Rust compiler prevent this.
pub struct Event {
    pub time: TimeSample,
    pub data: EventData,
}

// Having a large capacity here buys some time before having to implement Pause/Resume capabilities to hide
// the time spent in expanding the array. It may be a good idea to have the core API do a warmup and clear.
thread_local!(pub static EVENTS: UnsafeCell<Vec<Event>> = UnsafeCell::new(Vec::with_capacity(8192)));