Consistent formatting pass: line wrapping, import sorting, trailing whitespace removal, let-chain indentation, merged derive attributes, and unsafe block reformatting. Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
159 lines
4.8 KiB
Rust
159 lines
4.8 KiB
Rust
//! Profile results and aggregation.
|
|
|
|
use crate::config::{DeviceType, ModelType};
|
|
use crate::metrics::{LatencyMetrics, MemoryMetrics, ThroughputMetrics};
|
|
use serde::{Deserialize, Serialize};
|
|
|
|
/// Single profiling result for a specific configuration.
|
|
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
pub struct ProfileResult {
|
|
/// Model that was profiled
|
|
pub model_type: ModelType,
|
|
/// Device used for profiling
|
|
pub device: DeviceType,
|
|
/// Batch size tested
|
|
pub batch_size: usize,
|
|
/// Latency measurements
|
|
pub latency: LatencyMetrics,
|
|
/// Memory usage
|
|
pub memory: MemoryMetrics,
|
|
/// Throughput statistics
|
|
pub throughput: ThroughputMetrics,
|
|
/// Unix timestamp when profile was captured
|
|
pub timestamp: u64,
|
|
}
|
|
|
|
impl ProfileResult {
|
|
/// Creates a new profile result.
|
|
#[must_use]
|
|
pub fn new(
|
|
model_type: ModelType,
|
|
device: DeviceType,
|
|
batch_size: usize,
|
|
latency: LatencyMetrics,
|
|
memory: MemoryMetrics,
|
|
throughput: ThroughputMetrics,
|
|
timestamp: u64,
|
|
) -> Self {
|
|
Self {
|
|
model_type,
|
|
device,
|
|
batch_size,
|
|
latency,
|
|
memory,
|
|
throughput,
|
|
timestamp,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
#[test]
|
|
fn test_profile_result_creation() {
|
|
let latency = LatencyMetrics::from_measurements(&[10.0, 20.0, 30.0]).unwrap();
|
|
let memory = MemoryMetrics::new(100.0, 80.0, 120.0).unwrap();
|
|
let throughput = ThroughputMetrics::new(50.0, None).unwrap();
|
|
|
|
let result = ProfileResult::new(
|
|
ModelType::ResNet18,
|
|
DeviceType::CPU,
|
|
8,
|
|
latency,
|
|
memory,
|
|
throughput,
|
|
1234567890,
|
|
);
|
|
|
|
assert_eq!(result.model_type, ModelType::ResNet18);
|
|
assert_eq!(result.device, DeviceType::CPU);
|
|
assert_eq!(result.batch_size, 8);
|
|
assert_eq!(result.timestamp, 1234567890);
|
|
}
|
|
|
|
#[test]
|
|
fn test_profile_result_serialization() {
|
|
let latency = LatencyMetrics::from_measurements(&[10.0, 20.0, 30.0]).unwrap();
|
|
let memory = MemoryMetrics::new(100.0, 80.0, 120.0).unwrap();
|
|
let throughput = ThroughputMetrics::new(50.0, None).unwrap();
|
|
|
|
let result = ProfileResult::new(
|
|
ModelType::ViTB16,
|
|
DeviceType::CUDA,
|
|
16,
|
|
latency,
|
|
memory,
|
|
throughput,
|
|
1234567890,
|
|
);
|
|
|
|
let json = serde_json::to_string(&result).expect("serialization failed");
|
|
assert!(json.contains("\"model_type\""));
|
|
assert!(json.contains("\"vit-b16\""));
|
|
assert!(json.contains("\"batch_size\""));
|
|
assert!(json.contains("\"latency\""));
|
|
assert!(json.contains("\"memory\""));
|
|
assert!(json.contains("\"throughput\""));
|
|
}
|
|
|
|
#[test]
|
|
fn test_profile_result_deserialization() {
|
|
let json = r#"{
|
|
"model_type": "resnet50",
|
|
"device": "CUDA",
|
|
"batch_size": 32,
|
|
"latency": {
|
|
"mean_ms": 20.0,
|
|
"std_ms": 2.0,
|
|
"min_ms": 18.0,
|
|
"max_ms": 25.0,
|
|
"p50_ms": 20.0,
|
|
"p95_ms": 23.0,
|
|
"p99_ms": 24.0
|
|
},
|
|
"memory": {
|
|
"peak_memory_mb": 200.0,
|
|
"allocated_mb": 180.0,
|
|
"reserved_mb": 220.0
|
|
},
|
|
"throughput": {
|
|
"samples_per_sec": 1600.0,
|
|
"tokens_per_sec": null
|
|
},
|
|
"timestamp": 1234567890
|
|
}"#;
|
|
|
|
let result: ProfileResult = serde_json::from_str(json).expect("deserialization failed");
|
|
assert_eq!(result.model_type, ModelType::ResNet50);
|
|
assert_eq!(result.device, DeviceType::CUDA);
|
|
assert_eq!(result.batch_size, 32);
|
|
}
|
|
|
|
#[test]
|
|
fn test_profile_result_roundtrip() {
|
|
let latency = LatencyMetrics::from_measurements(&[10.0, 20.0, 30.0]).unwrap();
|
|
let memory = MemoryMetrics::new(100.0, 80.0, 120.0).unwrap();
|
|
let throughput = ThroughputMetrics::new(50.0, Some(200.0)).unwrap();
|
|
|
|
let original = ProfileResult::new(
|
|
ModelType::ConvNeXtBase,
|
|
DeviceType::Metal,
|
|
4,
|
|
latency,
|
|
memory,
|
|
throughput,
|
|
9876543210,
|
|
);
|
|
|
|
let json = serde_json::to_string(&original).expect("serialization failed");
|
|
let decoded: ProfileResult = serde_json::from_str(&json).expect("deserialization failed");
|
|
|
|
assert_eq!(decoded.model_type, original.model_type);
|
|
assert_eq!(decoded.device, original.device);
|
|
assert_eq!(decoded.batch_size, original.batch_size);
|
|
assert_eq!(decoded.timestamp, original.timestamp);
|
|
}
|
|
}
|