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
96use 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 (`label`, `log`, `capacity`, `iter`, 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
166use crate::Format;
167use crate::Section;
168
169#[inline]
170pub fn measure_sync<T, F: FnOnce() -> T>(_measurement_loc: &'static str, f: F) -> T {
171    f()
172}
173
174#[inline]
175pub fn measure_sync_log<T: std::fmt::Debug, F: FnOnce() -> T>(
176    _measurement_loc: &'static str,
177    f: F,
178) -> T {
179    f()
180}
181
182pub async fn measure_async<T, Fut>(_measurement_loc: &'static str, fut: Fut) -> T
183where
184    Fut: std::future::Future<Output = T>,
185{
186    fut.await
187}
188
189pub async fn measure_async_log<T: std::fmt::Debug, Fut>(
190    _measurement_loc: &'static str,
191    fut: Fut,
192) -> T
193where
194    Fut: std::future::Future<Output = T>,
195{
196    fut.await
197}
198
199pub async fn measure_async_future<T, Fut>(_measurement_loc: &'static str, fut: Fut) -> T
200where
201    Fut: std::future::Future<Output = T>,
202{
203    fut.await
204}
205
206pub async fn measure_async_future_log<T: std::fmt::Debug, Fut>(
207    _measurement_loc: &'static str,
208    fut: Fut,
209) -> T
210where
211    Fut: std::future::Future<Output = T>,
212{
213    fut.await
214}
215
216pub struct HotpathGuard;
217
218impl Default for HotpathGuard {
219    fn default() -> Self {
220        Self::new()
221    }
222}
223
224impl HotpathGuard {
225    pub(crate) fn new() -> Self {
226        Self {}
227    }
228}
229
230pub struct HotpathGuardBuilder {}
231
232impl HotpathGuardBuilder {
233    pub fn new(_caller_name: &'static str) -> Self {
234        Self {}
235    }
236
237    pub fn percentiles(self, _percentiles: &[f64]) -> Self {
238        self
239    }
240
241    pub fn format(self, _format: Format) -> Self {
242        self
243    }
244
245    pub fn functions_limit(self, _limit: usize) -> Self {
246        self
247    }
248
249    pub fn channels_limit(self, _limit: usize) -> Self {
250        self
251    }
252
253    pub fn streams_limit(self, _limit: usize) -> Self {
254        self
255    }
256
257    pub fn futures_limit(self, _limit: usize) -> Self {
258        self
259    }
260
261    pub fn threads_limit(self, _limit: usize) -> Self {
262        self
263    }
264
265    pub fn rw_locks_limit(self, _limit: usize) -> Self {
266        self
267    }
268
269    pub fn mutexes_limit(self, _limit: usize) -> Self {
270        self
271    }
272
273    pub fn sql_limit(self, _limit: usize) -> Self {
274        self
275    }
276
277    pub fn http_limit(self, _limit: usize) -> Self {
278        self
279    }
280
281    pub fn server_limit(self, _limit: usize) -> Self {
282        self
283    }
284
285    pub fn io_limit(self, _limit: usize) -> Self {
286        self
287    }
288
289    #[cfg(feature = "axum-0-8")]
290    pub fn route_scope(self, _enabled: bool) -> Self {
291        self
292    }
293
294    pub fn limit(self, _limit: usize) -> Self {
295        self
296    }
297
298    pub fn time_sampling_rate(self, _rate: f64) -> Self {
299        self
300    }
301
302    pub fn functions_time_sampling_rate(self, _rate: f64) -> Self {
303        self
304    }
305
306    pub fn mutexes_time_sampling_rate(self, _rate: f64) -> Self {
307        self
308    }
309
310    pub fn rw_locks_time_sampling_rate(self, _rate: f64) -> Self {
311        self
312    }
313
314    pub fn futures_time_sampling_rate(self, _rate: f64) -> Self {
315        self
316    }
317
318    pub fn channels_time_sampling_rate(self, _rate: f64) -> Self {
319        self
320    }
321
322    pub fn io_time_sampling_rate(self, _rate: f64) -> Self {
323        self
324    }
325
326    pub fn output_path(self, _path: impl AsRef<std::path::Path>) -> Self {
327        self
328    }
329
330    pub fn sections(self, _sections: Vec<Section>) -> Self {
331        self
332    }
333
334    pub fn sections_exclude(self, _sections: Vec<Section>) -> Self {
335        self
336    }
337
338    pub fn report(self, _spec: &str) -> Self {
339        self
340    }
341
342    pub fn before_shutdown(self, _f: impl FnOnce() + Send + 'static) -> Self {
343        self
344    }
345
346    pub fn user_metadata(self, _metadata: std::collections::HashMap<String, String>) -> Self {
347        self
348    }
349
350    pub fn build(self) -> HotpathGuard {
351        HotpathGuard
352    }
353
354    pub fn build_with_shutdown(self, _duration: std::time::Duration) {}
355}
356
357#[macro_export]
358macro_rules! axum {
359    ($router:expr) => {
360        $router
361    };
362}
363
364/// No-op tower layer used when the `hotpath-meta` feature is disabled. Lets
365/// call sites keep `.layer(hotpath_meta::AxumLayer::new())` in their router
366/// setup unconditionally - it returns the inner service untouched.
367#[cfg(feature = "axum-0-8")]
368#[derive(Default, Clone, Copy, Debug)]
369pub struct AxumLayer;
370
371#[cfg(feature = "axum-0-8")]
372impl AxumLayer {
373    pub fn new() -> Self {
374        Self
375    }
376}
377
378#[cfg(feature = "axum-0-8")]
379impl<S> tower_layer::Layer<S> for AxumLayer {
380    type Service = S;
381
382    fn layer(&self, inner: S) -> Self::Service {
383        inner
384    }
385}
386
387#[macro_export]
388macro_rules! rw_lock {
389    ($expr:expr) => {
390        $expr
391    };
392    ($expr:expr, label = $label:expr) => {
393        $expr
394    };
395}
396
397#[macro_export]
398macro_rules! mutex {
399    ($expr:expr) => {
400        $expr
401    };
402    ($expr:expr, label = $label:expr) => {
403        $expr
404    };
405}
406
407/// No-op counterpart of the enabled-mode `io_unwrap`. `io!` returns its
408/// argument unchanged when profiling is disabled, so unwrapping is the
409/// identity and call sites compile identically in both modes.
410pub fn io_unwrap<T>(io: T) -> T {
411    io
412}
413
414#[macro_export]
415macro_rules! io {
416    ($expr:expr) => {
417        $expr
418    };
419    ($expr:expr, label = $label:expr) => {
420        $expr
421    };
422    ($expr:expr, iter = true) => {
423        $expr
424    };
425    ($expr:expr, label = $label:expr, iter = true) => {
426        $expr
427    };
428    ($expr:expr, iter = true, label = $label:expr) => {
429        $expr
430    };
431}