#[cfg(feature = "alloc")]
use alloc::{
string::String,
vec::Vec,
};
#[cfg(feature = "alloc")]
type MetadataMap = Vec<(String, String)>;
use crate::types::*;
#[derive(Debug, Clone, PartialEq)]
pub struct PerformanceMetrics {
pub operation: OperationType,
pub algorithm: AlgorithmType,
pub execution_time_ns: u64,
pub memory_usage_bytes: usize,
pub iterations: u32,
pub success_rate: f64,
pub metadata: MetadataMap,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum OperationType {
KemKeyGeneration,
KemEncapsulation,
KemDecapsulation,
KdfExtract,
KdfExpand,
AeadSeal,
AeadOpen,
HpkeSetupSender,
HpkeSetupReceiver,
HpkeSeal,
HpkeOpen,
HpkeExport,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum AlgorithmType {
MlKem512,
MlKem768,
MlKem1024,
HkdfShake128,
HkdfShake256,
HkdfSha3_256,
HkdfSha3_512,
Saturnin256,
Shake256Aead,
DuplexSpongeAead,
ExportOnly,
}
impl PerformanceMetrics {
pub fn new(
operation: OperationType,
algorithm: AlgorithmType,
execution_time_ns: u64,
memory_usage_bytes: usize,
iterations: u32,
success_rate: f64,
) -> Self {
Self {
operation,
algorithm,
execution_time_ns,
memory_usage_bytes,
iterations,
success_rate,
metadata: Vec::new(),
}
}
pub fn with_metadata(mut self, key: String, value: String) -> Self {
self.metadata.push((key, value));
self
}
pub fn avg_execution_time_ns(&self) -> f64 {
if self.iterations > 0 {
self.execution_time_ns as f64 / self.iterations as f64
} else {
0.0
}
}
pub fn throughput_ops_per_sec(&self) -> f64 {
if self.execution_time_ns > 0 {
1_000_000_000.0 / self.avg_execution_time_ns()
} else {
0.0
}
}
pub fn memory_efficiency_bytes_per_op(&self) -> f64 {
if self.iterations > 0 {
self.memory_usage_bytes as f64 / self.iterations as f64
} else {
0.0
}
}
}
pub struct MetricsCollector {
metrics: Vec<PerformanceMetrics>,
}
impl MetricsCollector {
pub fn new() -> Self {
Self {
metrics: Vec::new(),
}
}
pub fn add_metrics(&mut self, metrics: PerformanceMetrics) {
self.metrics.push(metrics);
}
pub fn get_metrics(&self) -> &[PerformanceMetrics] {
&self.metrics
}
pub fn get_metrics_for_operation(&self, operation: OperationType) -> Vec<&PerformanceMetrics> {
self.metrics
.iter()
.filter(|m| m.operation == operation)
.collect()
}
pub fn get_metrics_for_algorithm(&self, algorithm: AlgorithmType) -> Vec<&PerformanceMetrics> {
self.metrics
.iter()
.filter(|m| m.algorithm == algorithm)
.collect()
}
pub fn get_average_metrics_for_operation(
&self,
operation: OperationType,
) -> Option<PerformanceMetrics> {
let operation_metrics: Vec<&PerformanceMetrics> = self.get_metrics_for_operation(operation);
if operation_metrics.is_empty() {
return None;
}
let total_time = operation_metrics
.iter()
.map(|m| m.execution_time_ns)
.sum::<u64>();
let total_memory = operation_metrics
.iter()
.map(|m| m.memory_usage_bytes)
.sum::<usize>();
let total_iterations = operation_metrics.iter().map(|m| m.iterations).sum::<u32>();
let avg_success_rate = operation_metrics
.iter()
.map(|m| m.success_rate)
.sum::<f64>() /
operation_metrics.len() as f64;
Some(PerformanceMetrics::new(
operation,
operation_metrics[0].algorithm, total_time,
total_memory,
total_iterations,
avg_success_rate,
))
}
pub fn clear(&mut self) {
self.metrics.clear();
}
pub fn len(&self) -> usize {
self.metrics.len()
}
pub fn is_empty(&self) -> bool {
self.metrics.is_empty()
}
}
impl Default for MetricsCollector {
fn default() -> Self {
Self::new()
}
}
impl From<HpkeKem> for AlgorithmType {
fn from(kem: HpkeKem) -> Self {
match kem {
HpkeKem::MlKem512 => AlgorithmType::MlKem512,
HpkeKem::MlKem768 => AlgorithmType::MlKem768,
HpkeKem::MlKem1024 => AlgorithmType::MlKem1024,
}
}
}
impl From<HpkeKdf> for AlgorithmType {
fn from(kdf: HpkeKdf) -> Self {
match kdf {
HpkeKdf::HkdfShake128 => AlgorithmType::HkdfShake128,
HpkeKdf::HkdfShake256 => AlgorithmType::HkdfShake256,
HpkeKdf::HkdfSha3_256 => AlgorithmType::HkdfSha3_256,
HpkeKdf::HkdfSha3_512 => AlgorithmType::HkdfSha3_512,
}
}
}
impl From<HpkeAead> for AlgorithmType {
fn from(aead: HpkeAead) -> Self {
match aead {
HpkeAead::Saturnin256 => AlgorithmType::Saturnin256,
HpkeAead::Shake256 => AlgorithmType::Shake256Aead,
HpkeAead::DuplexSpongeAead => AlgorithmType::DuplexSpongeAead,
HpkeAead::Export => AlgorithmType::ExportOnly,
}
}
}