use mudra_cli::{
CacheConfig, ConversionRequest, CurrencyClient, CurrencyConverter, ExchangeRateService,
};
use std::time::Instant;
pub async fn benchmark_conversion_performance() {
println!("🚀 Running Currency Converter Benchmarks");
println!("==========================================");
if std::env::var("EXCHANGE_API_KEY").is_err() {
println!("⚠️ EXCHANGE_API_KEY not set - using synthetic benchmarks");
benchmark_type_operations().await;
return;
}
let client = CurrencyClient::from_env().unwrap();
let service = ExchangeRateService::new(client);
let converter = CurrencyConverter::new(service);
println!("\n📊 Cache Performance Test");
println!("-------------------------");
let start = Instant::now();
let request = ConversionRequest::from_components(100.0, "USD", "EUR").unwrap();
let _result = converter.convert(request).await.unwrap();
let first_duration = start.elapsed();
let start = Instant::now();
let request = ConversionRequest::from_components(200.0, "USD", "EUR").unwrap();
let _result = converter.convert(request).await.unwrap();
let second_duration = start.elapsed();
println!("First request (cache miss): {:?}", first_duration);
println!("Second request (cache hit): {:?}", second_duration);
println!(
"Cache speedup: {:.2}x",
first_duration.as_millis() as f64 / second_duration.as_millis() as f64
);
println!("\n🔄 Batch Conversion Performance");
println!("-------------------------------");
let batch_requests = vec![
ConversionRequest::from_components(100.0, "USD", "EUR").unwrap(),
ConversionRequest::from_components(100.0, "USD", "GBP").unwrap(),
ConversionRequest::from_components(100.0, "USD", "JPY").unwrap(),
ConversionRequest::from_components(100.0, "USD", "CAD").unwrap(),
ConversionRequest::from_components(100.0, "USD", "AUD").unwrap(),
];
let start = Instant::now();
let _results = converter.convert_batch(batch_requests).await;
let batch_duration = start.elapsed();
println!("Batch conversion (5 currencies): {:?}", batch_duration);
println!("Average per conversion: {:?}", batch_duration / 5);
let stats = converter.exchange_service.get_cache_stats();
println!("\n📈 Cache Statistics");
println!("-------------------");
println!("Total requests: {}", stats.total_requests);
println!("Cache hits: {}", stats.hits);
println!("Cache misses: {}", stats.misses);
println!("Hit rate: {:.1}%", stats.hit_rate);
println!("Cached entries: {}", stats.cached_entries);
}
async fn benchmark_type_operations() {
println!("\n⚡ Type System Performance");
println!("-------------------------");
let start = Instant::now();
for _ in 0..10000 {
let _currency = mudra_cli::Currency::new("USD").unwrap();
}
let currency_duration = start.elapsed();
println!("10,000 Currency creations: {:?}", currency_duration);
println!("Average per creation: {:?}", currency_duration / 10000);
let start = Instant::now();
for i in 0..10000 {
let _money = mudra_cli::Money::from_code(i as f64, "USD").unwrap();
}
let money_duration = start.elapsed();
println!("10,000 Money creations: {:?}", money_duration);
println!("Average per creation: {:?}", money_duration / 10000);
let start = Instant::now();
for i in 0..10000 {
let _request = ConversionRequest::from_components(i as f64, "USD", "EUR").unwrap();
}
let request_duration = start.elapsed();
println!("10,000 ConversionRequest creations: {:?}", request_duration);
println!("Average per creation: {:?}", request_duration / 10000);
let money = mudra_cli::Money::from_code(123.456789, "USD").unwrap();
let start = Instant::now();
for _ in 0..100000 {
let _rounded = money.round(2);
}
let rounding_duration = start.elapsed();
println!("100,000 Money rounding operations: {:?}", rounding_duration);
println!("Average per rounding: {:?}", rounding_duration / 100000);
}
pub async fn benchmark_memory_usage() {
println!("\n💾 Memory Usage Analysis");
println!("------------------------");
let cache_config = CacheConfig {
max_capacity: 1000,
latest_ttl: 300,
historical_ttl: 3600,
enable_stats: true,
};
println!("Cache configuration:");
println!(" Max capacity: {}", cache_config.max_capacity);
println!(" Latest TTL: {}s", cache_config.latest_ttl);
println!(" Historical TTL: {}s", cache_config.historical_ttl);
println!("\nType sizes:");
println!(
" Currency: {} bytes",
std::mem::size_of::<mudra_cli::Currency>()
);
println!(" Money: {} bytes", std::mem::size_of::<mudra_cli::Money>());
println!(
" ConversionRequest: {} bytes",
std::mem::size_of::<ConversionRequest>()
);
println!(
" ConversionResult: {} bytes",
std::mem::size_of::<mudra_cli::ConversionResult>()
);
}
pub async fn benchmark_cache_stress_test() {
if std::env::var("EXCHANGE_API_KEY").is_err() {
println!("⚠️ Skipping cache stress test - no API key");
return;
}
println!("\n🔥 Cache Stress Test");
println!("-------------------");
let client = CurrencyClient::from_env().unwrap();
let service = ExchangeRateService::new(client);
let converter = CurrencyConverter::new(service);
let currencies = [
"EUR", "GBP", "JPY", "CAD", "AUD", "CHF", "CNY", "SEK", "NOK", "DKK",
];
let mut requests = Vec::new();
for from in ¤cies {
for to in ¤cies {
if from != to {
requests.push(ConversionRequest::from_components(100.0, from, to).unwrap());
}
}
}
println!("Generated {} conversion requests", requests.len());
let start = Instant::now();
let results = converter.convert_batch(requests).await;
let total_duration = start.elapsed();
let successful = results.iter().filter(|r| r.is_ok()).count();
let failed = results.len() - successful;
println!("Completed in: {:?}", total_duration);
println!("Successful conversions: {}", successful);
println!("Failed conversions: {}", failed);
println!(
"Average per conversion: {:?}",
total_duration / results.len() as u32
);
let stats = converter.exchange_service.get_cache_stats();
println!("Final cache hit rate: {:.1}%", stats.hit_rate);
println!(
"Cache efficiency: {} entries for {} currencies",
stats.cached_entries,
currencies.len()
);
}
#[tokio::main]
async fn main() {
benchmark_conversion_performance().await;
benchmark_memory_usage().await;
benchmark_cache_stress_test().await;
println!("\n✅ Benchmarks completed!");
println!("\nTo run with real API:");
println!("EXCHANGE_API_KEY=your_key cargo run --bin benchmarks");
}