Files
rustytorch/demos/inference-profiler-shared/src/ipc.rs
T
2026-03-04 00:08:42 +00:00

327 lines
10 KiB
Rust

//! IPC message types for profiler communication.
use crate::config::ProfileConfig;
use crate::error::ProfilerError;
use crate::results::ProfileResult;
use serde::{Deserialize, Serialize};
/// Request messages from UI to backend.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum ProfilerRequest {
/// Initialize profiler with configuration
Initialize {
/// Profile configuration
config: ProfileConfig,
},
/// Run profiling benchmark
RunProfile,
/// Get current results
GetResults,
/// Check device availability
CheckDeviceAvailability,
/// Reset profiler state
Reset,
}
/// Response messages from backend to UI.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
#[serde(tag = "type", rename_all = "kebab-case")]
pub enum ProfilerResponse {
/// Initialization successful
InitializeSuccess,
/// Profiling in progress
ProfilingProgress {
/// Current batch size index
batch_index: usize,
/// Total number of batches
total_batches: usize,
/// Current iteration
iteration: usize,
/// Total iterations for this batch
total_iterations: usize,
},
/// Profiling completed
ProfilingComplete {
/// All profile results
results: Vec<ProfileResult>,
},
/// Results response
Results {
/// Profile results
results: Vec<ProfileResult>,
},
/// Device availability status
DeviceAvailability {
/// Available devices
available_devices: Vec<String>,
},
/// Reset successful
ResetSuccess,
/// Error occurred
Error {
/// Error details
error: ProfilerError,
},
}
#[cfg(test)]
mod tests {
use super::*;
use crate::config::{DeviceType, ModelType};
use crate::metrics::{LatencyMetrics, MemoryMetrics, ThroughputMetrics};
#[test]
fn test_profiler_request_initialize_serialization() {
let config = ProfileConfig::default();
let request = ProfilerRequest::Initialize {
config: config.clone(),
};
let json = serde_json::to_string(&request).expect("serialization failed");
assert!(json.contains("\"type\""));
assert!(json.contains("\"initialize\""));
assert!(json.contains("\"config\""));
}
#[test]
fn test_profiler_request_run_profile_serialization() {
let request = ProfilerRequest::RunProfile;
let json = serde_json::to_string(&request).expect("serialization failed");
assert!(json.contains("\"run-profile\""));
}
#[test]
fn test_profiler_request_get_results_serialization() {
let request = ProfilerRequest::GetResults;
let json = serde_json::to_string(&request).expect("serialization failed");
assert!(json.contains("\"get-results\""));
}
#[test]
fn test_profiler_request_check_device_serialization() {
let request = ProfilerRequest::CheckDeviceAvailability;
let json = serde_json::to_string(&request).expect("serialization failed");
assert!(json.contains("\"check-device-availability\""));
}
#[test]
fn test_profiler_request_reset_serialization() {
let request = ProfilerRequest::Reset;
let json = serde_json::to_string(&request).expect("serialization failed");
assert!(json.contains("\"reset\""));
}
#[test]
fn test_profiler_request_deserialization() {
let json = r#"{"type":"run-profile"}"#;
let request: ProfilerRequest = serde_json::from_str(json).expect("deserialization failed");
match request {
ProfilerRequest::RunProfile => {}
_ => panic!("wrong request variant"),
}
}
#[test]
fn test_profiler_request_initialize_deserialization() {
let json = r#"{
"type": "initialize",
"config": {
"model_type": "resnet18",
"device": "CPU",
"batch_sizes": [1, 2, 4],
"warmup_iterations": 10,
"benchmark_iterations": 100,
"input_shape": {
"channels": 3,
"height": 224,
"width": 224
}
}
}"#;
let request: ProfilerRequest = serde_json::from_str(json).expect("deserialization failed");
match request {
ProfilerRequest::Initialize { config } => {
assert_eq!(config.model_type, ModelType::ResNet18);
assert_eq!(config.device, DeviceType::CPU);
}
_ => panic!("wrong request variant"),
}
}
#[test]
fn test_profiler_request_roundtrip() {
let requests = vec![
ProfilerRequest::Initialize {
config: ProfileConfig::default(),
},
ProfilerRequest::RunProfile,
ProfilerRequest::GetResults,
ProfilerRequest::CheckDeviceAvailability,
ProfilerRequest::Reset,
];
for request in requests {
let json = serde_json::to_string(&request).expect("serialization failed");
let decoded: ProfilerRequest =
serde_json::from_str(&json).expect("deserialization failed");
assert_eq!(request, decoded);
}
}
#[test]
fn test_profiler_response_initialize_success_serialization() {
let response = ProfilerResponse::InitializeSuccess;
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"initialize-success\""));
}
#[test]
fn test_profiler_response_profiling_progress_serialization() {
let response = ProfilerResponse::ProfilingProgress {
batch_index: 2,
total_batches: 5,
iteration: 50,
total_iterations: 100,
};
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"profiling-progress\""));
assert!(json.contains("\"batch_index\""));
assert!(json.contains("\"total_batches\""));
}
#[test]
fn test_profiler_response_profiling_complete_serialization() {
let latency = LatencyMetrics::from_measurements(&[10.0, 20.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,
);
let response = ProfilerResponse::ProfilingComplete {
results: vec![result],
};
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"profiling-complete\""));
assert!(json.contains("\"results\""));
}
#[test]
fn test_profiler_response_results_serialization() {
let response = ProfilerResponse::Results { results: vec![] };
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"results\""));
}
#[test]
fn test_profiler_response_device_availability_serialization() {
let response = ProfilerResponse::DeviceAvailability {
available_devices: vec!["CPU".to_string(), "CUDA".to_string()],
};
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"device-availability\""));
assert!(json.contains("\"available_devices\""));
}
#[test]
fn test_profiler_response_reset_success_serialization() {
let response = ProfilerResponse::ResetSuccess;
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"reset-success\""));
}
#[test]
fn test_profiler_response_error_serialization() {
let response = ProfilerResponse::Error {
error: ProfilerError::DeviceUnavailable("CUDA not found".to_string()),
};
let json = serde_json::to_string(&response).expect("serialization failed");
assert!(json.contains("\"error\""));
}
#[test]
fn test_profiler_response_deserialization() {
let json = r#"{"type":"initialize-success"}"#;
let response: ProfilerResponse =
serde_json::from_str(json).expect("deserialization failed");
match response {
ProfilerResponse::InitializeSuccess => {}
_ => panic!("wrong response variant"),
}
}
#[test]
fn test_profiler_response_progress_deserialization() {
let json = r#"{
"type": "profiling-progress",
"batch_index": 3,
"total_batches": 8,
"iteration": 75,
"total_iterations": 100
}"#;
let response: ProfilerResponse =
serde_json::from_str(json).expect("deserialization failed");
match response {
ProfilerResponse::ProfilingProgress {
batch_index,
total_batches,
iteration,
total_iterations,
} => {
assert_eq!(batch_index, 3);
assert_eq!(total_batches, 8);
assert_eq!(iteration, 75);
assert_eq!(total_iterations, 100);
}
_ => panic!("wrong response variant"),
}
}
#[test]
fn test_profiler_response_roundtrip() {
let responses = vec![
ProfilerResponse::InitializeSuccess,
ProfilerResponse::ProfilingProgress {
batch_index: 1,
total_batches: 4,
iteration: 50,
total_iterations: 100,
},
ProfilerResponse::Results { results: vec![] },
ProfilerResponse::DeviceAvailability {
available_devices: vec!["CPU".to_string()],
},
ProfilerResponse::ResetSuccess,
ProfilerResponse::Error {
error: ProfilerError::ConfigError("test".to_string()),
},
];
for response in responses {
let json = serde_json::to_string(&response).expect("serialization failed");
let decoded: ProfilerResponse =
serde_json::from_str(&json).expect("deserialization failed");
assert_eq!(response, decoded);
}
}
}