Skip to main content

pprof_alloc/trace/
mod.rs

1#[cfg(not(all(
2	feature = "frame-pointer",
3	target_os = "linux",
4	any(target_arch = "x86_64", target_arch = "aarch64")
5)))]
6use backtrace::trace;
7#[cfg(all(
8	feature = "frame-pointer",
9	target_os = "linux",
10	any(target_arch = "x86_64", target_arch = "aarch64")
11))]
12use frame_pointer::trace;
13
14use itertools::Itertools;
15use serde::Serialize;
16use smallvec::SmallVec;
17use std::fmt;
18use std::hash::{Hash, Hasher};
19
20#[cfg(not(all(
21	feature = "frame-pointer",
22	target_os = "linux",
23	any(target_arch = "x86_64", target_arch = "aarch64")
24)))]
25mod backtrace;
26#[cfg(all(
27	feature = "frame-pointer",
28	target_os = "linux",
29	any(target_arch = "x86_64", target_arch = "aarch64")
30))]
31mod frame_pointer;
32
33const SOFT_MAX_DEPTH: usize = 128;
34
35#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize)]
36pub enum CaptureMode {
37	FramePointer,
38	Backtrace,
39}
40
41#[cfg(all(
42	feature = "frame-pointer",
43	target_os = "linux",
44	any(target_arch = "x86_64", target_arch = "aarch64")
45))]
46pub const fn capture_mode() -> CaptureMode {
47	CaptureMode::FramePointer
48}
49
50#[cfg(not(all(
51	feature = "frame-pointer",
52	target_os = "linux",
53	any(target_arch = "x86_64", target_arch = "aarch64")
54)))]
55pub const fn capture_mode() -> CaptureMode {
56	CaptureMode::Backtrace
57}
58
59#[derive(Clone)]
60struct UnresolvedFrames(SmallVec<[u64; SOFT_MAX_DEPTH]>);
61
62impl From<SmallVec<[u64; SOFT_MAX_DEPTH]>> for UnresolvedFrames {
63	fn from(x: SmallVec<[u64; SOFT_MAX_DEPTH]>) -> Self {
64		Self(x)
65	}
66}
67
68#[derive(Clone)]
69pub struct HashedBacktrace {
70	inner: UnresolvedFrames,
71	hash: u64,
72}
73
74impl fmt::Debug for HashedBacktrace {
75	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
76		let address = self.inner.0.iter().map(|x| format!("{:#x}", x)).join(" ");
77		f.write_str(&address)
78	}
79}
80
81impl HashedBacktrace {
82	pub fn capture() -> Self {
83		let bt = trace();
84		let mut hasher = ahash::AHasher::default();
85		bt.0.iter().for_each(|x| hasher.write_u64(*x));
86		let hash = hasher.finish();
87		Self { inner: bt, hash }
88	}
89	pub fn addrs(&self) -> Vec<u64> {
90		self.inner.0.iter().copied().collect_vec()
91	}
92}
93
94impl PartialEq for HashedBacktrace {
95	fn eq(&self, other: &Self) -> bool {
96		self.hash == other.hash && self.inner.0 == other.inner.0
97	}
98}
99
100impl Eq for HashedBacktrace {}
101
102impl Hash for HashedBacktrace {
103	fn hash<H: Hasher>(&self, state: &mut H) {
104		self.inner.0.iter().for_each(|x| state.write_u64(*x));
105	}
106}