use scirs2_core::numeric::Float;
use std::collections::{BTreeMap, HashMap, VecDeque};
use std::fmt::Debug;
use std::fs::File;
use std::io::Write;
use std::sync::{Arc, Mutex, RwLock};
use std::time::{Duration, Instant, SystemTime};
use super::super::frontend::XLAComputation;
use super::BackendConfig;
use crate::error::{OptimError, Result};
pub struct ProfilingIntegration<T> {
config: ProfilingConfig,
counter_manager: PerformanceCounterManager,
trace_collector: TraceCollector,
memory_profiler: MemoryProfiler,
power_profiler: PowerProfiler,
timeline_profiler: TimelineProfiler<T>,
data_aggregator: ProfilingDataAggregator,
export_manager: ProfileExportManager,
profiling_stats: ProfilingStatistics,
}
#[derive(Debug, Clone)]
pub struct ProfilingConfig {
pub enable_perf_counters: bool,
pub enable_trace_collection: bool,
pub enable_memory_profiling: bool,
pub enable_power_profiling: bool,
pub enable_timeline_profiling: bool,
pub sampling_rate: u64,
pub max_trace_buffer_mb: usize,
pub output_directory: String,
pub export_format: ExportFormat,
pub detailed_mode: bool,
}
#[derive(Debug, Clone)]
pub enum ExportFormat {
JSON,
ProtoBuf,
ChromeTrace,
CSV,
Binary,
}
#[derive(Debug, Default)]
pub struct ProfilingStatistics {
pub samples_collected: u64,
pub trace_events: u64,
pub memory_snapshots: u64,
pub power_samples: u64,
pub profiling_overhead_us: u64,
pub export_time_us: u64,
}
pub struct PerformanceCounterManager {
available_counters: HashMap<String, CounterInfo>,
active_sessions: HashMap<String, CounterSession>,
counter_data: Arc<RwLock<HashMap<String, CounterTimeSeries>>>,
counter_config: CounterConfig,
}
#[derive(Debug, Clone)]
pub struct CounterInfo {
pub name: String,
pub description: String,
pub counter_type: CounterType,
pub units: String,
pub granularity: CounterGranularity,
pub hardware_dependency: Option<String>,
}
#[derive(Debug, Clone)]
pub enum CounterType {
Cumulative,
Gauge,
Rate,
Histogram,
}
#[derive(Debug, Clone)]
pub enum CounterGranularity {
Instruction,
Operation,
Kernel,
Execution,
System,
}
#[derive(Debug)]
pub struct CounterSession {
pub id: String,
pub start_time: Instant,
pub enabled_counters: Vec<String>,
pub sample_buffer: VecDeque<CounterSample>,
pub config: SessionConfig,
}
#[derive(Debug, Clone)]
pub struct CounterSample {
pub timestamp: Instant,
pub counter_name: String,
pub value: CounterValue,
pub context: Option<String>,
}
#[derive(Debug, Clone)]
pub enum CounterValue {
Integer(i64),
Float(f64),
Boolean(bool),
String(String),
Histogram(Vec<(f64, u64)>),
}
#[derive(Debug)]
pub struct CounterTimeSeries {
pub counter_name: String,
pub samples: Vec<(Instant, CounterValue)>,
pub statistics: TimeSeriesStats,
}
#[derive(Debug, Default)]
pub struct TimeSeriesStats {
pub min: f64,
pub max: f64,
pub average: f64,
pub std_dev: f64,
pub sample_count: usize,
}
#[derive(Debug, Clone)]
pub struct SessionConfig {
pub sampling_interval_us: u64,
pub buffer_size: usize,
pub auto_flush_threshold: usize,
pub include_context: bool,
}
#[derive(Debug)]
pub struct CounterConfig {
pub default_sampling_rate: u64,
pub counter_groups: HashMap<String, Vec<String>>,
pub aliases: HashMap<String, String>,
}
pub struct TraceCollector {
trace_buffer: Arc<Mutex<TraceBuffer>>,
trace_sessions: HashMap<String, TraceSession>,
event_filters: Vec<EventFilter>,
trace_config: TraceConfig,
}
#[derive(Debug)]
pub struct TraceBuffer {
pub events: VecDeque<TraceEvent>,
pub max_size: usize,
pub current_size: usize,
pub stats: BufferStats,
}
#[derive(Debug, Clone)]
pub struct TraceEvent {
pub id: u64,
pub timestamp: Instant,
pub event_type: EventType,
pub phase: EventPhase,
pub thread_id: Option<u64>,
pub process_id: Option<u64>,
pub name: String,
pub category: String,
pub duration: Option<Duration>,
pub args: HashMap<String, String>,
pub stack_trace: Option<Vec<String>>,
}
#[derive(Debug, Clone)]
pub enum EventType {
FunctionCall,
KernelExecution,
MemoryOperation,
Communication,
Synchronization,
ResourceAllocation,
Custom(String),
}
#[derive(Debug, Clone)]
pub enum EventPhase {
Begin,
End,
Instant,
Complete,
AsyncBegin,
AsyncEnd,
}
#[derive(Debug)]
pub struct TraceSession {
pub id: String,
pub start_time: Instant,
pub enabled_events: Vec<EventType>,
pub session_buffer: Vec<TraceEvent>,
pub metadata: TraceMetadata,
}
#[derive(Debug, Default)]
pub struct TraceMetadata {
pub session_name: String,
pub target_executable: Option<String>,
pub hardware_info: HashMap<String, String>,
pub software_info: HashMap<String, String>,
}
#[derive(Debug)]
pub struct EventFilter {
pub name: String,
pub event_type_filter: Option<EventType>,
pub category_filter: Option<String>,
pub duration_threshold: Option<Duration>,
pub include: bool,
}
#[derive(Debug, Default)]
pub struct BufferStats {
pub events_written: u64,
pub events_dropped: u64,
pub overruns: u64,
pub peak_usage: usize,
}
#[derive(Debug)]
pub struct TraceConfig {
pub buffer_size: usize,
pub include_stack_traces: bool,
pub max_stack_depth: usize,
pub enable_compression: bool,
}
pub struct MemoryProfiler {
tracking_sessions: HashMap<String, MemoryTrackingSession>,
allocation_tracker: AllocationTracker,
usage_snapshots: Vec<MemorySnapshot>,
memory_config: MemoryProfilingConfig,
}
#[derive(Debug)]
pub struct MemoryTrackingSession {
pub id: String,
pub start_time: Instant,
pub allocations: HashMap<usize, AllocationInfo>,
pub stats: MemoryTrackingStats,
}
#[derive(Debug)]
pub struct AllocationInfo {
pub address: usize,
pub size: usize,
pub timestamp: Instant,
pub source: AllocationSource,
pub stack_trace: Option<Vec<String>>,
pub tags: Vec<String>,
}
#[derive(Debug)]
pub enum AllocationSource {
Kernel(String),
Runtime,
User,
Unknown,
}
#[derive(Debug, Default)]
pub struct MemoryTrackingStats {
pub total_allocations: usize,
pub total_deallocations: usize,
pub current_allocations: usize,
pub peak_memory_usage: usize,
pub current_memory_usage: usize,
pub fragmentation_ratio: f64,
}
pub struct AllocationTracker {
active_allocations: HashMap<usize, AllocationInfo>,
allocation_history: Vec<AllocationEvent>,
tracker_config: TrackerConfig,
}
#[derive(Debug)]
pub struct AllocationEvent {
pub timestamp: Instant,
pub event_type: AllocationEventType,
pub address: usize,
pub size: usize,
pub context: Option<String>,
}
#[derive(Debug)]
pub enum AllocationEventType {
Allocate,
Deallocate,
Reallocate,
}
#[derive(Debug)]
pub struct TrackerConfig {
pub track_stack_traces: bool,
pub max_history_size: usize,
pub enable_leak_detection: bool,
}
#[derive(Debug)]
pub struct MemorySnapshot {
pub timestamp: Instant,
pub regions: Vec<MemoryRegion>,
pub total_usage: usize,
pub fragmentation: FragmentationInfo,
}
#[derive(Debug)]
pub struct MemoryRegion {
pub start_address: usize,
pub size: usize,
pub region_type: MemoryRegionType,
pub usage: RegionUsage,
}
#[derive(Debug)]
pub enum MemoryRegionType {
Code,
Data,
Stack,
Heap,
Device,
}
#[derive(Debug)]
pub struct RegionUsage {
pub used_bytes: usize,
pub free_bytes: usize,
pub fragmentation: f64,
}
#[derive(Debug, Default)]
pub struct FragmentationInfo {
pub external_fragmentation: f64,
pub internal_fragmentation: f64,
pub largest_free_block: usize,
pub free_block_count: usize,
}
#[derive(Debug)]
pub struct MemoryProfilingConfig {
pub snapshot_interval_ms: u64,
pub track_allocations: bool,
pub max_snapshots: usize,
pub enable_heap_profiling: bool,
}
pub struct PowerProfiler {
monitoring_sessions: HashMap<String, PowerMonitoringSession>,
power_samples: Vec<PowerSample>,
power_config: PowerProfilingConfig,
power_model: PowerModel,
}
#[derive(Debug)]
pub struct PowerMonitoringSession {
pub id: String,
pub start_time: Instant,
pub components: Vec<PowerComponent>,
pub samples: Vec<PowerSample>,
}
#[derive(Debug, Clone)]
pub enum PowerComponent {
CPU,
TPU,
Memory,
Interconnect,
System,
}
#[derive(Debug, Clone)]
pub struct PowerSample {
pub timestamp: Instant,
pub component: PowerComponent,
pub power_watts: f64,
pub voltage: Option<f64>,
pub current: Option<f64>,
pub temperature: Option<f64>,
}
#[derive(Debug)]
pub struct PowerProfilingConfig {
pub sampling_rate: u64,
pub component_level_monitoring: bool,
pub include_thermal: bool,
pub model_accuracy: PowerModelAccuracy,
}
#[derive(Debug)]
pub enum PowerModelAccuracy {
Low,
Medium,
High,
}
pub struct PowerModel {
parameters: HashMap<String, f64>,
component_models: HashMap<PowerComponent, ComponentPowerModel>,
}
#[derive(Debug)]
pub struct ComponentPowerModel {
pub base_power: f64,
pub dynamic_factors: HashMap<String, f64>,
pub thermal_coefficients: Vec<f64>,
}
pub struct TimelineProfiler<T> {
sessions: HashMap<String, TimelineSession>,
timeline_data: Vec<TimelineEntry>,
timeline_config: TimelineConfig,
_phantom: std::marker::PhantomData<T>,
}
#[derive(Debug)]
pub struct TimelineSession {
pub id: String,
pub start_time: Instant,
pub operations: HashMap<String, OperationTimeline>,
pub metadata: TimelineMetadata,
}
#[derive(Debug)]
pub struct OperationTimeline {
pub operation_id: String,
pub start_time: Instant,
pub end_time: Option<Instant>,
pub events: Vec<TimelineEvent>,
pub resource_usage: Vec<ResourceUsagePoint>,
}
#[derive(Debug)]
pub struct TimelineEvent {
pub timestamp: Instant,
pub description: String,
pub data: HashMap<String, String>,
}
#[derive(Debug)]
pub struct ResourceUsagePoint {
pub timestamp: Instant,
pub cpu_utilization: f64,
pub memory_usage: usize,
pub tpu_utilization: f64,
pub power_consumption: f64,
}
#[derive(Debug)]
pub struct TimelineEntry {
pub timestamp: Instant,
pub entry_type: TimelineEntryType,
pub operation_id: Option<String>,
pub data: TimelineEntryData,
}
#[derive(Debug)]
pub enum TimelineEntryType {
OperationStart,
OperationEnd,
ResourceAllocation,
MemoryEvent,
CounterEvent,
}
#[derive(Debug)]
pub enum TimelineEntryData {
Operation(OperationTimelineData),
Resource(ResourceTimelineData),
Memory(MemoryTimelineData),
Counter(CounterTimelineData),
}
#[derive(Debug)]
pub struct OperationTimelineData {
pub name: String,
pub input_sizes: Vec<usize>,
pub output_sizes: Vec<usize>,
pub compute_intensity: f64,
}
#[derive(Debug)]
pub struct ResourceTimelineData {
pub resource_type: String,
pub amount: usize,
pub utilization: f64,
}
#[derive(Debug)]
pub struct MemoryTimelineData {
pub operation_type: String,
pub address: usize,
pub size: usize,
}
#[derive(Debug)]
pub struct CounterTimelineData {
pub counter_name: String,
pub value: CounterValue,
pub delta: Option<f64>,
}
#[derive(Debug, Default)]
pub struct TimelineMetadata {
pub session_name: String,
pub start_time: Option<SystemTime>,
pub end_time: Option<SystemTime>,
pub total_operations: usize,
}
#[derive(Debug)]
pub struct TimelineConfig {
pub detailed_operations: bool,
pub include_resources: bool,
pub resolution_us: u64,
pub max_entries: usize,
}
pub struct ProfilingDataAggregator {
aggregated_data: HashMap<String, AggregatedMetrics>,
aggregation_config: AggregationConfig,
}
#[derive(Debug, Default)]
pub struct AggregatedMetrics {
pub performance: PerformanceMetrics,
pub memory: MemoryMetrics,
pub power: PowerMetrics,
pub timeline: TimelineMetrics,
}
#[derive(Debug, Default)]
pub struct PerformanceMetrics {
pub avg_execution_time_us: f64,
pub throughput: f64,
pub compute_utilization: f64,
pub memory_bandwidth_util: f64,
}
#[derive(Debug, Default)]
pub struct MemoryMetrics {
pub peak_usage_bytes: usize,
pub avg_usage_bytes: f64,
pub efficiency: f64,
pub allocation_rate: f64,
}
#[derive(Debug, Default)]
pub struct PowerMetrics {
pub avg_power_watts: f64,
pub peak_power_watts: f64,
pub energy_joules: f64,
pub efficiency: f64,
}
#[derive(Debug, Default)]
pub struct TimelineMetrics {
pub total_operations: usize,
pub avg_operation_duration_us: f64,
pub critical_path_length_us: u64,
pub parallelization_efficiency: f64,
}
#[derive(Debug)]
pub struct AggregationConfig {
pub interval_seconds: u64,
pub real_time: bool,
pub retention_hours: u32,
}
pub struct ProfileExportManager {
export_config: ExportConfig,
export_stats: ExportStatistics,
}
#[derive(Debug)]
pub struct ExportConfig {
pub format: ExportFormat,
pub output_dir: String,
pub include_raw_data: bool,
pub compression: bool,
pub include_metadata: bool,
}
#[derive(Debug, Default)]
pub struct ExportStatistics {
pub files_exported: usize,
pub total_size_bytes: usize,
pub export_time_us: u64,
pub compression_ratio: f64,
}
impl<T: Float + Debug + Send + Sync + 'static> ProfilingIntegration<T> {
pub fn new(config: &BackendConfig) -> Self {
let profiling_config = ProfilingConfig {
enable_perf_counters: config.enable_profiling,
enable_trace_collection: config.enable_profiling,
enable_memory_profiling: config.enable_profiling,
enable_power_profiling: false,
enable_timeline_profiling: config.enable_profiling,
sampling_rate: 1000, max_trace_buffer_mb: 100,
output_directory: "/tmp/scirs_profiles".to_string(),
export_format: ExportFormat::JSON,
detailed_mode: config.debug_mode,
};
Self {
counter_manager: PerformanceCounterManager::new(),
trace_collector: TraceCollector::new(&profiling_config),
memory_profiler: MemoryProfiler::new(&profiling_config),
power_profiler: PowerProfiler::new(&profiling_config),
timeline_profiler: TimelineProfiler::new(&profiling_config),
data_aggregator: ProfilingDataAggregator::new(),
export_manager: ProfileExportManager::new(&profiling_config),
config: profiling_config,
profiling_stats: ProfilingStatistics::default(),
}
}
pub fn setup_profiling(
&mut self,
_computation: &XLAComputation<T>,
_binary: &[u8],
) -> Result<()> {
if self.config.enable_perf_counters {
self.counter_manager.start_session("main_session")?;
}
if self.config.enable_trace_collection {
self.trace_collector.start_tracing("main_trace")?;
}
if self.config.enable_memory_profiling {
self.memory_profiler.start_tracking("main_memory")?;
}
if self.config.enable_timeline_profiling {
self.timeline_profiler.start_timeline("main_timeline")?;
}
Ok(())
}
pub fn export_data(&mut self) -> Result<Vec<String>> {
let mut exported_files = Vec::new();
if self.config.enable_perf_counters {
let file_path = self
.export_manager
.export_counter_data(&self.counter_manager)?;
exported_files.push(file_path);
}
if self.config.enable_trace_collection {
let file_path = self
.export_manager
.export_trace_data(&self.trace_collector)?;
exported_files.push(file_path);
}
if self.config.enable_memory_profiling {
let file_path = self
.export_manager
.export_memory_data(&self.memory_profiler)?;
exported_files.push(file_path);
}
Ok(exported_files)
}
pub fn reset(&mut self) {
self.profiling_stats = ProfilingStatistics::default();
self.counter_manager.reset();
self.trace_collector.reset();
self.memory_profiler.reset();
self.timeline_profiler.reset();
}
}
impl Default for PerformanceCounterManager {
fn default() -> Self {
Self::new()
}
}
impl PerformanceCounterManager {
pub fn new() -> Self {
let mut available_counters = HashMap::new();
available_counters.insert(
"matrix_ops".to_string(),
CounterInfo {
name: "matrix_ops".to_string(),
description: "Matrix operations executed".to_string(),
counter_type: CounterType::Cumulative,
units: "operations".to_string(),
granularity: CounterGranularity::Operation,
hardware_dependency: Some("matrix_unit".to_string()),
},
);
available_counters.insert(
"memory_bandwidth".to_string(),
CounterInfo {
name: "memory_bandwidth".to_string(),
description: "Memory bandwidth utilization".to_string(),
counter_type: CounterType::Gauge,
units: "GB/s".to_string(),
granularity: CounterGranularity::System,
hardware_dependency: Some("memory_controller".to_string()),
},
);
Self {
available_counters,
active_sessions: HashMap::new(),
counter_data: Arc::new(RwLock::new(HashMap::new())),
counter_config: CounterConfig {
default_sampling_rate: 1000,
counter_groups: HashMap::new(),
aliases: HashMap::new(),
},
}
}
pub fn start_session(&mut self, session_id: &str) -> Result<()> {
let session = CounterSession {
id: session_id.to_string(),
start_time: Instant::now(),
enabled_counters: self.available_counters.keys().cloned().collect(),
sample_buffer: VecDeque::new(),
config: SessionConfig {
sampling_interval_us: 1000, buffer_size: 10000,
auto_flush_threshold: 8000,
include_context: true,
},
};
self.active_sessions.insert(session_id.to_string(), session);
Ok(())
}
pub fn reset(&mut self) {
self.active_sessions.clear();
let mut data = self.counter_data.write().expect("lock poisoned");
data.clear();
}
}
impl TraceCollector {
pub fn new(config: &ProfilingConfig) -> Self {
Self {
trace_buffer: Arc::new(Mutex::new(TraceBuffer {
events: VecDeque::new(),
max_size: config.max_trace_buffer_mb * 1024 * 1024,
current_size: 0,
stats: BufferStats::default(),
})),
trace_sessions: HashMap::new(),
event_filters: Vec::new(),
trace_config: TraceConfig {
buffer_size: 100000,
include_stack_traces: config.detailed_mode,
max_stack_depth: 32,
enable_compression: true,
},
}
}
pub fn start_tracing(&mut self, session_id: &str) -> Result<()> {
let session = TraceSession {
id: session_id.to_string(),
start_time: Instant::now(),
enabled_events: vec![EventType::KernelExecution, EventType::MemoryOperation],
session_buffer: Vec::new(),
metadata: TraceMetadata::default(),
};
self.trace_sessions.insert(session_id.to_string(), session);
Ok(())
}
pub fn reset(&mut self) {
self.trace_sessions.clear();
let mut buffer = self.trace_buffer.lock().expect("lock poisoned");
buffer.events.clear();
buffer.current_size = 0;
buffer.stats = BufferStats::default();
}
}
impl MemoryProfiler {
pub fn new(_config: &ProfilingConfig) -> Self {
Self {
tracking_sessions: HashMap::new(),
allocation_tracker: AllocationTracker::new(),
usage_snapshots: Vec::new(),
memory_config: MemoryProfilingConfig {
snapshot_interval_ms: 100,
track_allocations: true,
max_snapshots: 1000,
enable_heap_profiling: true,
},
}
}
pub fn start_tracking(&mut self, session_id: &str) -> Result<()> {
let session = MemoryTrackingSession {
id: session_id.to_string(),
start_time: Instant::now(),
allocations: HashMap::new(),
stats: MemoryTrackingStats::default(),
};
self.tracking_sessions
.insert(session_id.to_string(), session);
Ok(())
}
pub fn reset(&mut self) {
self.tracking_sessions.clear();
self.usage_snapshots.clear();
self.allocation_tracker.reset();
}
}
impl Default for AllocationTracker {
fn default() -> Self {
Self::new()
}
}
impl AllocationTracker {
pub fn new() -> Self {
Self {
active_allocations: HashMap::new(),
allocation_history: Vec::new(),
tracker_config: TrackerConfig {
track_stack_traces: false,
max_history_size: 100000,
enable_leak_detection: true,
},
}
}
pub fn reset(&mut self) {
self.active_allocations.clear();
self.allocation_history.clear();
}
}
impl PowerProfiler {
pub fn new(_config: &ProfilingConfig) -> Self {
Self {
monitoring_sessions: HashMap::new(),
power_samples: Vec::new(),
power_config: PowerProfilingConfig {
sampling_rate: 10, component_level_monitoring: true,
include_thermal: true,
model_accuracy: PowerModelAccuracy::Medium,
},
power_model: PowerModel {
parameters: HashMap::new(),
component_models: HashMap::new(),
},
}
}
}
impl<T> TimelineProfiler<T> {
pub fn new(_config: &ProfilingConfig) -> Self {
Self {
sessions: HashMap::new(),
timeline_data: Vec::new(),
timeline_config: TimelineConfig {
detailed_operations: true,
include_resources: true,
resolution_us: 1, max_entries: 1000000,
},
_phantom: std::marker::PhantomData,
}
}
pub fn start_timeline(&mut self, session_id: &str) -> Result<()> {
let session = TimelineSession {
id: session_id.to_string(),
start_time: Instant::now(),
operations: HashMap::new(),
metadata: TimelineMetadata::default(),
};
self.sessions.insert(session_id.to_string(), session);
Ok(())
}
pub fn reset(&mut self) {
self.sessions.clear();
self.timeline_data.clear();
}
}
impl Default for ProfilingDataAggregator {
fn default() -> Self {
Self::new()
}
}
impl ProfilingDataAggregator {
pub fn new() -> Self {
Self {
aggregated_data: HashMap::new(),
aggregation_config: AggregationConfig {
interval_seconds: 1,
real_time: true,
retention_hours: 24,
},
}
}
}
impl ProfileExportManager {
pub fn new(config: &ProfilingConfig) -> Self {
Self {
export_config: ExportConfig {
format: config.export_format.clone(),
output_dir: config.output_directory.clone(),
include_raw_data: config.detailed_mode,
compression: true,
include_metadata: true,
},
export_stats: ExportStatistics::default(),
}
}
pub fn export_counter_data(
&mut self,
_counter_manager: &PerformanceCounterManager,
) -> Result<String> {
let filename = format!(
"{}/counters_{}.json",
self.export_config.output_dir,
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|e| OptimError::from(e.to_string()))?
.as_secs()
);
std::fs::create_dir_all(&self.export_config.output_dir)?;
let mut file = File::create(&filename)?;
writeln!(file, "{{\n \"counters\": [],\n \"metadata\": {{}}\n}}")?;
self.export_stats.files_exported += 1;
Ok(filename)
}
pub fn export_trace_data(&mut self, _trace_collector: &TraceCollector) -> Result<String> {
let filename = format!(
"{}/trace_{}.json",
self.export_config.output_dir,
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|e| OptimError::from(e.to_string()))?
.as_secs()
);
std::fs::create_dir_all(&self.export_config.output_dir)?;
let mut file = File::create(&filename)?;
writeln!(
file,
"{{\n \"traceEvents\": [],\n \"displayTimeUnit\": \"ns\"\n}}"
)?;
self.export_stats.files_exported += 1;
Ok(filename)
}
pub fn export_memory_data(&mut self, _memory_profiler: &MemoryProfiler) -> Result<String> {
let filename = format!(
"{}/memory_{}.json",
self.export_config.output_dir,
SystemTime::now()
.duration_since(SystemTime::UNIX_EPOCH)
.map_err(|e| OptimError::from(e.to_string()))?
.as_secs()
);
std::fs::create_dir_all(&self.export_config.output_dir)?;
let mut file = File::create(&filename)?;
writeln!(file, "{{\n \"snapshots\": [],\n \"allocations\": []\n}}")?;
self.export_stats.files_exported += 1;
Ok(filename)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_profiling_integration_creation() {
use super::super::{
super::super::PodTopology, super::TPUConfig, super::TPUVersion, BackendConfig,
};
let tpu_config = TPUConfig {
tpu_version: TPUVersion::V4,
num_cores: 8,
enable_xla: true,
xla_optimization_level: crate::main_types::XLAOptimizationLevel::Standard,
mixed_precision: true,
batch_size_per_core: 32,
enable_pod_coordination: false,
pod_topology: PodTopology::Pod2x2,
memory_optimization: crate::main_types::TPUMemoryOptimization::Balanced,
gradient_compression: true,
prefetch_depth: 2,
experimental_features: false,
};
let backend_config = BackendConfig {
target_tpu: tpu_config,
enable_optimized_codegen: true,
enable_profiling: true,
debug_mode: false,
verification_mode: false,
custom_options: std::collections::HashMap::new(),
};
let profiling: ProfilingIntegration<f32> = ProfilingIntegration::new(&backend_config);
assert_eq!(profiling.profiling_stats.samples_collected, 0);
assert!(profiling.config.enable_perf_counters);
}
#[test]
fn test_counter_manager_creation() {
let counter_manager = PerformanceCounterManager::new();
assert!(!counter_manager.available_counters.is_empty());
assert!(counter_manager
.available_counters
.contains_key("matrix_ops"));
assert!(counter_manager
.available_counters
.contains_key("memory_bandwidth"));
}
}