#[cfg(feature = "full_profiling")]
use thag_profiler::{current_allocator, safe_alloc, Allocator};
#[cfg(feature = "debug_logging")]
use thag_profiler::debug_log;
#[cfg(not(feature = "debug_logging"))]
macro_rules! debug_log {
($($arg:tt)*) => {};
}
#[cfg(feature = "full_profiling")]
use serial_test::serial;
#[cfg(feature = "full_profiling")]
fn reset_allocator_states() {
thag_profiler::mem_tracking::reset_allocator_state();
}
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
fn test_nested_global_behavior() {
thag_profiler::profiling::force_set_profiling_state(true);
reset_allocator_states();
assert_eq!(current_allocator(), Allocator::Tracking);
safe_alloc! {
assert_eq!(current_allocator(), Allocator::System);
safe_alloc! {
assert_eq!(current_allocator(), Allocator::System);
};
assert_eq!(current_allocator(), Allocator::System);
};
assert_eq!(current_allocator(), Allocator::Tracking);
}
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
fn test_thread_isolation() {
use std::{
sync::{Arc, Barrier},
thread,
};
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_states();
let barrier = Arc::new(Barrier::new(3));
let mut handles = vec![];
let barrier1 = barrier.clone();
handles.push(thread::spawn(move || {
barrier1.wait();
safe_alloc! {
assert_eq!(current_allocator(), Allocator::System);
thread::sleep(std::time::Duration::from_millis(10));
};
}));
let barrier2 = barrier.clone();
handles.push(thread::spawn(move || {
barrier2.wait();
safe_alloc! {
assert_eq!(current_allocator(), Allocator::System);
thread::sleep(std::time::Duration::from_millis(10));
};
}));
let barrier3 = barrier;
handles.push(thread::spawn(move || {
barrier3.wait();
thread::sleep(std::time::Duration::from_millis(5));
assert_eq!(current_allocator(), Allocator::Tracking);
}));
for handle in handles {
handle.join().unwrap();
}
}
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
#[allow(clippy::cast_precision_loss)]
fn test_performance_comparison() {
use std::time::Instant;
const ITERATIONS: usize = 1000;
thag_profiler::profiling::force_set_profiling_state(true);
reset_allocator_states();
let start = Instant::now();
for _ in 0..ITERATIONS {
safe_alloc! {
std::hint::black_box(current_allocator());
};
}
let global_duration = start.elapsed();
let start = Instant::now();
for _ in 0..ITERATIONS {
safe_alloc! {
std::hint::black_box(current_allocator());
};
}
let tls_duration = start.elapsed();
println!(
"Performance comparison ({} iterations):\n Global atomic: {:?}\n Thread-local: {:?}\n TLS speedup: {:.2}x",
ITERATIONS,
global_duration,
tls_duration,
global_duration.as_nanos() as f64 / tls_duration.as_nanos() as f64
);
}
#[test]
fn test_debug_log_zero_cost() {
debug_log!("This should be zero-cost when feature is disabled");
}
#[test]
#[cfg(feature = "debug_logging")]
fn test_debug_log_with_feature() {
debug_log!("This is a test message: {}", 42);
debug_log!("Multiple args: {} {} {}", "hello", "world", 123);
assert!(true);
}