use anyhow::Result;
use std::collections::HashMap;
use std::time::{Duration, Instant};
use trustformers_core::tensor::Tensor;
use trustformers_core::traits::Model;
use super::config::{TestDataType, TestInputConfig, ValidationConfig};
use super::types::{
LayerPerformance, MemoryAnalysis, OverallPerformance, PerformanceResults,
ThroughputMeasurements,
};
pub struct PerformanceProfiler {
config: ValidationConfig,
}
impl PerformanceProfiler {
pub fn new() -> Self {
Self {
config: ValidationConfig::default(),
}
}
pub fn with_config(config: ValidationConfig) -> Self {
Self { config }
}
pub fn profile_model<M: Model<Input = Tensor, Output = Tensor>>(
&self,
model: &M,
) -> Result<PerformanceResults> {
let mut layer_performance = Vec::new();
let mut total_time = Duration::ZERO;
let total_memory = 0.0;
for test_input in &self.config.test_inputs {
let input = self.create_test_input(test_input)?;
let start_time = Instant::now();
let _output = model.forward(input)?;
let inference_time = start_time.elapsed();
total_time += inference_time;
layer_performance.push(LayerPerformance {
layer_name: format!("layer_{}", layer_performance.len()),
layer_type: "transformer".to_string(),
forward_time: inference_time / 10, memory_usage_mb: 100.0, flops: None,
utilization_percent: None,
});
}
let overall_performance = OverallPerformance {
total_inference_time: total_time,
tokens_per_second: 1000.0, total_flops: None,
peak_memory_mb: total_memory,
average_memory_mb: total_memory / self.config.test_inputs.len() as f64,
};
let memory_analysis = MemoryAnalysis {
by_layer_type: HashMap::new(),
by_tensor_type: HashMap::new(),
efficiency_score: 75.0, fragmentation_percent: 5.0, };
let throughput = ThroughputMeasurements {
batch_size: 1,
sequence_length: 128,
tokens_per_second: 1000.0,
samples_per_second: 10.0,
latency_per_token_ms: 1.0,
};
Ok(PerformanceResults {
layer_performance,
overall_performance,
memory_analysis,
throughput,
})
}
fn create_test_input(&self, config: &TestInputConfig) -> Result<Tensor> {
match config.data_type {
TestDataType::I32 => {
let mut input_ids = Vec::new();
for i in 0..config.dimensions.iter().product::<usize>() {
input_ids.push(((i % 1000 + 1) as i32) as f32); }
Ok(Tensor::from_vec(input_ids, &config.dimensions)?)
},
TestDataType::F32 => {
Ok(Tensor::randn(&config.dimensions)?)
},
TestDataType::F16 => {
Ok(Tensor::randn(&config.dimensions)?)
},
TestDataType::I64 => {
let mut input_ids = Vec::new();
for i in 0..config.dimensions.iter().product::<usize>() {
input_ids.push(((i % 1000 + 1) as i64) as f32);
}
Ok(Tensor::from_vec(input_ids, &config.dimensions)?)
},
}
}
pub fn get_model_name(&self) -> &str {
"Unknown"
}
}
impl Default for PerformanceProfiler {
fn default() -> Self {
Self::new()
}
}