#[cfg(feature = "full_profiling")]
use serial_test::serial;
#[cfg(feature = "full_profiling")]
use std::sync::{Arc, Barrier};
#[cfg(feature = "full_profiling")]
use std::thread;
#[cfg(feature = "full_profiling")]
use thag_profiler::{current_allocator, safe_alloc, Allocator};
#[cfg(feature = "full_profiling")]
use thag_profiler::reset_allocator_state;
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
fn test_unified_allocator_basic() {
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_state();
assert_eq!(current_allocator(), Allocator::Tracking);
safe_alloc! {
assert_eq!(current_allocator(), Allocator::System);
};
assert_eq!(current_allocator(), Allocator::Tracking);
}
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
fn test_unified_allocator_nesting() {
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_state();
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_unified_allocator_threading() {
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_state();
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));
let current = current_allocator();
assert_eq!(current, Allocator::Tracking);
}));
for handle in handles {
handle.join().unwrap();
}
}
#[test]
#[cfg(feature = "full_profiling")]
#[serial]
fn test_unified_approach_selection() {
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_state();
println!("Testing thread-local allocator approach");
println!(" Using thread-local storage implementation");
assert_eq!(current_allocator(), Allocator::Tracking);
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_performance_characteristics() {
use std::time::Instant;
const ITERATIONS: usize = 1000;
thag_profiler::profiling::force_set_profiling_state(true);
assert!(thag_profiler::is_profiling_enabled());
reset_allocator_state();
let start = Instant::now();
for _ in 0..ITERATIONS {
safe_alloc! {
std::hint::black_box(current_allocator());
};
}
let duration = start.elapsed();
println!("TLS approach: {} iterations in {:?}", ITERATIONS, duration);
assert!(duration.as_nanos() > 0);
}
#[test]
#[cfg(feature = "full_profiling")]
fn test_advanced_api_availability() {
let _state = thag_profiler::current_allocator();
}