Skip to main content

hotpath_meta/
lib_off.rs

1pub use hotpath_macros_meta::{future_fn, main, measure, measure_all, skip};
2
3#[macro_export]
4macro_rules! measure_block {
5    ($label:expr, $expr:expr) => {{
6        $expr
7    }};
8}
9
10#[macro_export]
11macro_rules! dbg {
12    ($val:expr $(,)?) => {
13        match $val {
14            tmp => tmp
15        }
16    };
17    ($($val:expr),+ $(,)?) => {
18        ($($crate::dbg!($val)),+,)
19    };
20}
21
22#[macro_export]
23macro_rules! val {
24    ($key:expr) => {{
25        $crate::ValHandle
26    }};
27}
28
29/// No-op counterpart of the tracking allocator: a pure pass-through to the
30/// inner allocator, so a `#[global_allocator]` declaration compiles unchanged
31/// with the `hotpath-meta` feature disabled.
32pub struct CountingAllocator<A = std::alloc::System>(A);
33
34impl CountingAllocator<std::alloc::System> {
35    pub const fn new() -> Self {
36        Self(std::alloc::System)
37    }
38}
39
40impl<A> CountingAllocator<A> {
41    pub const fn with(inner: A) -> Self {
42        Self(inner)
43    }
44}
45
46impl<A: Default> Default for CountingAllocator<A> {
47    fn default() -> Self {
48        Self(A::default())
49    }
50}
51
52// SAFETY: pure pass-through - every pointer returned by
53// `alloc`/`alloc_zeroed`/`realloc` comes from the corresponding method of `A`,
54// and `dealloc`/`realloc` forward the caller's `ptr`/`layout`/`new_size`
55// unchanged, so `A`'s GlobalAlloc guarantees carry over.
56unsafe impl<A> std::alloc::GlobalAlloc for CountingAllocator<A>
57where
58    A: std::alloc::GlobalAlloc,
59{
60    unsafe fn alloc(&self, layout: std::alloc::Layout) -> *mut u8 {
61        // SAFETY: caller upholds GlobalAlloc's contract for `layout`; it is
62        // forwarded unchanged.
63        unsafe { self.0.alloc(layout) }
64    }
65
66    unsafe fn dealloc(&self, ptr: *mut u8, layout: std::alloc::Layout) {
67        // SAFETY: caller guarantees `ptr` was allocated by this allocator
68        // with `layout`, which means it came from `A::alloc`; both are
69        // forwarded unchanged.
70        unsafe {
71            self.0.dealloc(ptr, layout);
72        }
73    }
74
75    unsafe fn alloc_zeroed(&self, layout: std::alloc::Layout) -> *mut u8 {
76        // SAFETY: caller upholds GlobalAlloc's contract for `layout`; it is
77        // forwarded unchanged.
78        unsafe { self.0.alloc_zeroed(layout) }
79    }
80
81    unsafe fn realloc(&self, ptr: *mut u8, layout: std::alloc::Layout, new_size: usize) -> *mut u8 {
82        // SAFETY: caller guarantees `ptr` was allocated by this allocator
83        // with `layout` and that `new_size` is valid per GlobalAlloc's
84        // contract; all three are forwarded unchanged.
85        unsafe { self.0.realloc(ptr, layout, new_size) }
86    }
87}
88
89pub struct ValHandle;
90
91impl ValHandle {
92    #[inline]
93    pub fn set<T: std::fmt::Debug>(&self, _value: &T) {}
94}
95
96pub use crate::shared::IntoF64;
97
98#[macro_export]
99macro_rules! gauge {
100    ($key:expr) => {{
101        $crate::GaugeHandle
102    }};
103}
104
105pub struct GaugeHandle;
106
107impl GaugeHandle {
108    #[inline]
109    pub fn set(&self, _value: impl IntoF64) -> &Self {
110        self
111    }
112
113    #[inline]
114    pub fn inc(&self, _delta: impl IntoF64) -> &Self {
115        self
116    }
117
118    #[inline]
119    pub fn dec(&self, _delta: impl IntoF64) -> &Self {
120        self
121    }
122}
123
124#[macro_export]
125macro_rules! channel {
126    // Profiling disabled: every form (`wrap`, `label`, `log`, `capacity`, any order)
127    // returns the original channel unchanged.
128    ($expr:expr $(, $($rest:tt)*)?) => {
129        $expr
130    };
131}
132
133#[macro_export]
134macro_rules! stream {
135    // Profiling disabled: every form (`label`, `log`, `iter`, any order)
136    // returns the original stream unchanged.
137    ($expr:expr $(, $($rest:tt)*)?) => {
138        $expr
139    };
140}
141
142#[macro_export]
143macro_rules! tokio_runtime {
144    ($($handle:expr)?) => {};
145}
146
147#[macro_export]
148macro_rules! future {
149    ($fut:expr) => {
150        $fut
151    };
152    ($fut:expr, label = $label:expr) => {
153        $fut
154    };
155    ($fut:expr, log = true) => {
156        $fut
157    };
158    ($fut:expr, label = $label:expr, log = true) => {
159        $fut
160    };
161    ($fut:expr, log = true, label = $label:expr) => {
162        $fut
163    };
164}
165
166pub use crate::Format;
167pub use crate::Section;
168
169pub struct MeasurementGuard {}
170
171impl MeasurementGuard {
172    pub fn new(_name: &'static str, _wrapper: bool) -> Self {
173        Self {}
174    }
175
176    pub fn build(_name: &'static str, _wrapper: bool) -> Self {
177        Self {}
178    }
179}
180
181#[inline]
182pub fn measure_sync<T, F: FnOnce() -> T>(_measurement_loc: &'static str, f: F) -> T {
183    f()
184}
185
186#[inline]
187pub fn measure_sync_log<T: std::fmt::Debug, F: FnOnce() -> T>(
188    _measurement_loc: &'static str,
189    f: F,
190) -> T {
191    f()
192}
193
194pub async fn measure_async<T, Fut>(_measurement_loc: &'static str, fut: Fut) -> T
195where
196    Fut: std::future::Future<Output = T>,
197{
198    fut.await
199}
200
201pub async fn measure_async_log<T: std::fmt::Debug, Fut>(
202    _measurement_loc: &'static str,
203    fut: Fut,
204) -> T
205where
206    Fut: std::future::Future<Output = T>,
207{
208    fut.await
209}
210
211pub async fn measure_async_future<T, Fut>(_measurement_loc: &'static str, fut: Fut) -> T
212where
213    Fut: std::future::Future<Output = T>,
214{
215    fut.await
216}
217
218pub async fn measure_async_future_log<T: std::fmt::Debug, Fut>(
219    _measurement_loc: &'static str,
220    fut: Fut,
221) -> T
222where
223    Fut: std::future::Future<Output = T>,
224{
225    fut.await
226}
227
228pub struct HotpathGuard;
229
230impl Default for HotpathGuard {
231    fn default() -> Self {
232        Self::new()
233    }
234}
235
236impl HotpathGuard {
237    pub(crate) fn new() -> Self {
238        Self {}
239    }
240}
241
242pub struct HotpathGuardBuilder {}
243
244impl HotpathGuardBuilder {
245    pub fn new(_caller_name: &'static str) -> Self {
246        Self {}
247    }
248
249    pub fn percentiles(self, _percentiles: &[f64]) -> Self {
250        self
251    }
252
253    pub fn format(self, _format: Format) -> Self {
254        self
255    }
256
257    pub fn functions_limit(self, _limit: usize) -> Self {
258        self
259    }
260
261    pub fn channels_limit(self, _limit: usize) -> Self {
262        self
263    }
264
265    pub fn streams_limit(self, _limit: usize) -> Self {
266        self
267    }
268
269    pub fn futures_limit(self, _limit: usize) -> Self {
270        self
271    }
272
273    pub fn threads_limit(self, _limit: usize) -> Self {
274        self
275    }
276
277    pub fn rw_locks_limit(self, _limit: usize) -> Self {
278        self
279    }
280
281    pub fn mutexes_limit(self, _limit: usize) -> Self {
282        self
283    }
284
285    pub fn sql_limit(self, _limit: usize) -> Self {
286        self
287    }
288
289    pub fn http_limit(self, _limit: usize) -> Self {
290        self
291    }
292
293    pub fn io_limit(self, _limit: usize) -> Self {
294        self
295    }
296
297    pub fn limit(self, _limit: usize) -> Self {
298        self
299    }
300
301    pub fn time_sampling_rate(self, _rate: f64) -> Self {
302        self
303    }
304
305    pub fn functions_time_sampling_rate(self, _rate: f64) -> Self {
306        self
307    }
308
309    pub fn mutexes_time_sampling_rate(self, _rate: f64) -> Self {
310        self
311    }
312
313    pub fn rw_locks_time_sampling_rate(self, _rate: f64) -> Self {
314        self
315    }
316
317    pub fn futures_time_sampling_rate(self, _rate: f64) -> Self {
318        self
319    }
320
321    pub fn channels_time_sampling_rate(self, _rate: f64) -> Self {
322        self
323    }
324
325    pub fn io_time_sampling_rate(self, _rate: f64) -> Self {
326        self
327    }
328
329    pub fn output_path(self, _path: impl AsRef<std::path::Path>) -> Self {
330        self
331    }
332
333    pub fn sections(self, _sections: Vec<Section>) -> Self {
334        self
335    }
336
337    pub fn sections_exclude(self, _sections: Vec<Section>) -> Self {
338        self
339    }
340
341    pub fn report(self, _spec: &str) -> Self {
342        self
343    }
344
345    pub fn before_shutdown(self, _f: impl FnOnce() + Send + 'static) -> Self {
346        self
347    }
348
349    pub fn build(self) -> HotpathGuard {
350        HotpathGuard
351    }
352
353    pub fn build_with_shutdown(self, _duration: std::time::Duration) {}
354}
355
356pub mod channels {
357    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
358    pub enum ChannelType {
359        Bounded(usize),
360        Unbounded,
361        Oneshot,
362        Pending,
363    }
364}
365
366pub mod streams {}
367
368pub mod threads {}
369
370pub mod futures {}
371
372pub mod rw_locks {
373    pub use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
374}
375
376pub mod mutexes {
377    pub use std::sync::{Mutex, MutexGuard};
378}
379
380#[macro_export]
381macro_rules! rw_lock {
382    ($expr:expr) => {
383        $expr
384    };
385    ($expr:expr, label = $label:expr) => {
386        $expr
387    };
388}
389
390#[macro_export]
391macro_rules! mutex {
392    ($expr:expr) => {
393        $expr
394    };
395    ($expr:expr, label = $label:expr) => {
396        $expr
397    };
398}
399
400/// No-op counterpart of the enabled-mode `io_unwrap`. `io!` returns its
401/// argument unchanged when profiling is disabled, so unwrapping is the
402/// identity and call sites compile identically in both modes.
403pub fn io_unwrap<T>(io: T) -> T {
404    io
405}
406
407#[macro_export]
408macro_rules! io {
409    ($expr:expr) => {
410        $expr
411    };
412    ($expr:expr, label = $label:expr) => {
413        $expr
414    };
415    ($expr:expr, iter = true) => {
416        $expr
417    };
418    ($expr:expr, label = $label:expr, iter = true) => {
419        $expr
420    };
421    ($expr:expr, iter = true, label = $label:expr) => {
422        $expr
423    };
424}