#[macro_export]
macro_rules! profile_block {
($name:expr, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "block".to_string());
$block
}};
($name:expr, $category:expr, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), $category.to_string());
$block
}};
}
#[macro_export]
macro_rules! profile_current_function {
() => {
let _guard = $crate::cpu::ProfileScope::simple(
format!("{}::function", module_path!()),
"function".to_string(),
);
};
($category:expr) => {
let _guard = $crate::cpu::ProfileScope::simple(
format!("{}::function", module_path!()),
$category.to_string(),
);
};
}
#[macro_export]
macro_rules! profile_closure {
($name:expr, $closure:expr) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "closure".to_string());
$closure()
}};
($name:expr, $category:expr, $closure:expr) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), $category.to_string());
$closure()
}};
}
#[macro_export]
macro_rules! profile_alloc {
($name:expr, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "allocation".to_string());
$block
}};
}
#[macro_export]
macro_rules! profile_cuda {
($name:expr, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "cuda".to_string());
$block
}};
}
#[macro_export]
macro_rules! profile_tensor_op {
($name:expr, flops: $flops:expr, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "tensor_op".to_string());
$block
}};
}
#[macro_export]
macro_rules! profile_if {
($condition:expr, $name:expr, $block:block) => {{
if $condition {
let _guard =
$crate::cpu::ProfileScope::simple($name.to_string(), "conditional".to_string());
$block
} else {
$block
}
}};
}
#[macro_export]
macro_rules! profile_with_metadata {
($name:expr, { $($key:ident: $value:expr),* $(,)? }, $block:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "metadata".to_string());
$block
}};
}
#[macro_export]
macro_rules! profile_loop {
($name:expr, for $item:ident in $iter:expr, $body:block) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "loop".to_string());
for $item in $iter $body
}};
}
#[macro_export]
macro_rules! profile_async {
($name:expr, $future:expr) => {{
let _guard = $crate::cpu::ProfileScope::simple($name.to_string(), "async".to_string());
$future
}};
}
#[macro_export]
macro_rules! profile_compare {
($name:expr, { $($variant:expr => $block:block),* $(,)? }) => {{
let mut results = std::collections::HashMap::new();
$(
let start_time = std::time::Instant::now();
{
let _guard = $crate::cpu::ProfileScope::simple(
format!("{}_{}", $name, $variant),
"comparison".to_string()
);
$block
}
let duration = start_time.elapsed();
results.insert($variant.to_string(), duration);
)*
println!("Profile comparison for {}:", $name);
let mut sorted_results: Vec<_> = results.iter().collect();
sorted_results.sort_by(|a, b| a.1.cmp(b.1));
for (variant, duration) in sorted_results {
println!(" {}: {:?}", variant, duration);
}
results
}};
}
#[macro_export]
macro_rules! profiling_scope {
($name:expr) => {
let _profiling_guard =
$crate::cpu::ProfileScope::simple($name.to_string(), "scope".to_string());
};
($name:expr, $category:expr) => {
let _profiling_guard =
$crate::cpu::ProfileScope::simple($name.to_string(), $category.to_string());
};
}
#[macro_export]
macro_rules! profile_with_overhead {
($name:expr, $block:block) => {{
let overhead_start = std::time::Instant::now();
let _guard =
$crate::cpu::ProfileScope::simple($name.to_string(), "overhead_measured".to_string());
let setup_overhead = overhead_start.elapsed();
let operation_start = std::time::Instant::now();
let result = $block;
let operation_duration = operation_start.elapsed();
let teardown_start = std::time::Instant::now();
drop(_guard);
let teardown_overhead = teardown_start.elapsed();
let total_overhead = setup_overhead + teardown_overhead;
(
ProfileResult {
result,
duration: operation_duration,
},
total_overhead,
)
}};
}
pub struct ProfileResult<T> {
pub result: T,
pub duration: std::time::Duration,
}
#[macro_export]
macro_rules! profile_sampled {
($name:expr, sample_rate: $rate:expr, $block:block) => {{
use std::sync::atomic::{AtomicUsize, Ordering};
static CALL_COUNT: AtomicUsize = AtomicUsize::new(0);
let call_num = CALL_COUNT.fetch_add(1, Ordering::Relaxed);
if call_num % $rate == 0 {
let _guard = $crate::cpu::ProfileScope::simple(
format!("{}_sample_{}", $name, call_num / $rate),
"sampled".to_string(),
);
$block
} else {
$block
}
}};
}
#[macro_export]
macro_rules! profile_thread_local {
($name:expr, $block:block) => {{
thread_local! {
static PROFILER: std::cell::RefCell<$crate::cpu::CpuProfiler> =
std::cell::RefCell::new($crate::cpu::CpuProfiler::new());
}
let start_time = std::time::Instant::now();
let result = $block;
let duration = start_time.elapsed();
PROFILER.with(|profiler| {
let mut profiler = profiler.borrow_mut();
let _ = profiler.record_event($name, "thread_local", duration);
});
result
}};
}
#[cfg(test)]
mod tests {
use super::*;
use std::time::Duration;
#[test]
fn test_profile_block_macro() {
let result = profile_block!("test_block", {
std::thread::sleep(Duration::from_millis(1));
42
});
assert_eq!(result, 42);
}
#[test]
fn test_profile_closure_macro() {
let result = profile_closure!("test_closure", || {
std::thread::sleep(Duration::from_millis(1));
"success"
});
assert_eq!(result, "success");
}
#[test]
fn test_profile_if_macro() {
let result = profile_if!(true, "conditional_test", {
std::thread::sleep(Duration::from_millis(1));
"executed"
});
assert_eq!(result, "executed");
let result = profile_if!(false, "conditional_test", {
std::thread::sleep(Duration::from_millis(1));
"also_executed"
});
assert_eq!(result, "also_executed");
}
#[test]
fn test_profile_compare_macro() {
let mut data1 = vec![3, 1, 4, 1, 5, 9, 2, 6];
let mut data2 = data1.clone();
let results = profile_compare!("sorting_test", {
"sort" => { data1.sort(); },
"sort_unstable" => { data2.sort_unstable(); }
});
assert_eq!(results.len(), 2);
assert!(results.contains_key("sort"));
assert!(results.contains_key("sort_unstable"));
}
#[test]
fn test_profile_sampled_macro() {
let mut execution_count = 0;
for _ in 0..10 {
profile_sampled!("sampled_test", sample_rate: 3, {
execution_count += 1;
});
}
assert_eq!(execution_count, 10); }
#[test]
fn test_profile_with_overhead_macro() {
let (result, overhead) = profile_with_overhead!("overhead_test", {
std::thread::sleep(Duration::from_millis(1));
"test_result"
});
assert_eq!(result.result, "test_result");
assert!(result.duration >= Duration::from_millis(1));
assert!(overhead < Duration::from_millis(1)); }
#[test]
fn test_profiling_scope_macro() {
profiling_scope!("test_scope");
std::thread::sleep(Duration::from_millis(1));
}
#[test]
fn test_profile_thread_local_macro() {
let result = profile_thread_local!("thread_local_test", {
std::thread::sleep(Duration::from_millis(1));
"thread_result"
});
assert_eq!(result, "thread_result");
}
#[tokio::test]
async fn test_profile_async_macro() {
let result = profile_async!("async_test", async {
tokio::time::sleep(Duration::from_millis(1)).await;
"async_result"
})
.await;
assert_eq!(result, "async_result");
}
}