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 server_limit(self, _limit: usize) -> Self {
294        self
295    }
296
297    pub fn io_limit(self, _limit: usize) -> Self {
298        self
299    }
300
301    #[cfg(feature = "axum-0-8")]
302    pub fn route_scope(self, _enabled: bool) -> Self {
303        self
304    }
305
306    pub fn limit(self, _limit: usize) -> Self {
307        self
308    }
309
310    pub fn time_sampling_rate(self, _rate: f64) -> Self {
311        self
312    }
313
314    pub fn functions_time_sampling_rate(self, _rate: f64) -> Self {
315        self
316    }
317
318    pub fn mutexes_time_sampling_rate(self, _rate: f64) -> Self {
319        self
320    }
321
322    pub fn rw_locks_time_sampling_rate(self, _rate: f64) -> Self {
323        self
324    }
325
326    pub fn futures_time_sampling_rate(self, _rate: f64) -> Self {
327        self
328    }
329
330    pub fn channels_time_sampling_rate(self, _rate: f64) -> Self {
331        self
332    }
333
334    pub fn io_time_sampling_rate(self, _rate: f64) -> Self {
335        self
336    }
337
338    pub fn output_path(self, _path: impl AsRef<std::path::Path>) -> Self {
339        self
340    }
341
342    pub fn sections(self, _sections: Vec<Section>) -> Self {
343        self
344    }
345
346    pub fn sections_exclude(self, _sections: Vec<Section>) -> Self {
347        self
348    }
349
350    pub fn report(self, _spec: &str) -> Self {
351        self
352    }
353
354    pub fn before_shutdown(self, _f: impl FnOnce() + Send + 'static) -> Self {
355        self
356    }
357
358    pub fn build(self) -> HotpathGuard {
359        HotpathGuard
360    }
361
362    pub fn build_with_shutdown(self, _duration: std::time::Duration) {}
363}
364
365pub mod channels {
366    #[derive(Debug, Clone, Copy, PartialEq, Eq)]
367    pub enum ChannelType {
368        Bounded(usize),
369        Unbounded,
370        Oneshot,
371        Pending,
372    }
373}
374
375pub mod streams {}
376
377pub mod threads {}
378
379pub mod futures {}
380
381pub mod rw_locks {
382    pub use std::sync::{RwLock, RwLockReadGuard, RwLockWriteGuard};
383}
384
385pub mod mutexes {
386    pub use std::sync::{Mutex, MutexGuard};
387}
388
389#[macro_export]
390macro_rules! axum {
391    ($router:expr) => {
392        $router
393    };
394}
395
396/// No-op tower layer used when the `hotpath-meta` feature is disabled. Lets
397/// call sites keep `.layer(hotpath_meta::AxumLayer::new())` in their router
398/// setup unconditionally - it returns the inner service untouched.
399#[cfg(feature = "axum-0-8")]
400#[derive(Default, Clone, Copy, Debug)]
401pub struct AxumLayer;
402
403#[cfg(feature = "axum-0-8")]
404impl AxumLayer {
405    pub fn new() -> Self {
406        Self
407    }
408}
409
410#[cfg(feature = "axum-0-8")]
411impl<S> tower_layer::Layer<S> for AxumLayer {
412    type Service = S;
413
414    fn layer(&self, inner: S) -> Self::Service {
415        inner
416    }
417}
418
419#[macro_export]
420macro_rules! rw_lock {
421    ($expr:expr) => {
422        $expr
423    };
424    ($expr:expr, label = $label:expr) => {
425        $expr
426    };
427}
428
429#[macro_export]
430macro_rules! mutex {
431    ($expr:expr) => {
432        $expr
433    };
434    ($expr:expr, label = $label:expr) => {
435        $expr
436    };
437}
438
439/// No-op counterpart of the enabled-mode `io_unwrap`. `io!` returns its
440/// argument unchanged when profiling is disabled, so unwrapping is the
441/// identity and call sites compile identically in both modes.
442pub fn io_unwrap<T>(io: T) -> T {
443    io
444}
445
446#[macro_export]
447macro_rules! io {
448    ($expr:expr) => {
449        $expr
450    };
451    ($expr:expr, label = $label:expr) => {
452        $expr
453    };
454    ($expr:expr, iter = true) => {
455        $expr
456    };
457    ($expr:expr, label = $label:expr, iter = true) => {
458        $expr
459    };
460    ($expr:expr, iter = true, label = $label:expr) => {
461        $expr
462    };
463}