512 lines
14 KiB
Rust
512 lines
14 KiB
Rust
//! 性能优化系统
|
||
//!
|
||
//! 实现完整的性能优化功能,包括存储优化、计算优化、Gas优化和并发处理
|
||
|
||
use std::collections::HashMap;
|
||
use std::sync::{Arc, Mutex, RwLock};
|
||
|
||
/// 存储优化器
|
||
#[derive(Debug)]
|
||
pub struct StorageOptimizer {
|
||
/// 缓存
|
||
cache: Arc<RwLock<HashMap<String, CachedValue>>>,
|
||
/// 缓存大小限制
|
||
max_cache_size: usize,
|
||
/// 缓存命中次数
|
||
cache_hits: Arc<Mutex<u64>>,
|
||
/// 缓存未命中次数
|
||
cache_misses: Arc<Mutex<u64>>,
|
||
}
|
||
|
||
/// 缓存值
|
||
#[derive(Debug, Clone)]
|
||
struct CachedValue {
|
||
/// 值
|
||
value: Vec<u8>,
|
||
/// 过期时间
|
||
expiry: u64,
|
||
/// 访问次数
|
||
access_count: u64,
|
||
}
|
||
|
||
impl StorageOptimizer {
|
||
/// 创建新的存储优化器
|
||
pub fn new(max_cache_size: usize) -> Self {
|
||
Self {
|
||
cache: Arc::new(RwLock::new(HashMap::new())),
|
||
max_cache_size,
|
||
cache_hits: Arc::new(Mutex::new(0)),
|
||
cache_misses: Arc::new(Mutex::new(0)),
|
||
}
|
||
}
|
||
|
||
/// 从缓存获取值
|
||
pub fn get(&self, key: &str) -> Option<Vec<u8>> {
|
||
let mut cache = self.cache.write().unwrap();
|
||
|
||
if let Some(cached) = cache.get_mut(key) {
|
||
// 检查是否过期
|
||
if cached.expiry > Self::current_timestamp() {
|
||
cached.access_count += 1;
|
||
*self.cache_hits.lock().unwrap() += 1;
|
||
return Some(cached.value.clone());
|
||
} else {
|
||
// 过期,移除
|
||
cache.remove(key);
|
||
}
|
||
}
|
||
|
||
*self.cache_misses.lock().unwrap() += 1;
|
||
None
|
||
}
|
||
|
||
/// 设置缓存值
|
||
pub fn set(&self, key: String, value: Vec<u8>, ttl: u64) {
|
||
let mut cache = self.cache.write().unwrap();
|
||
|
||
// 如果缓存已满,移除最少使用的项
|
||
if cache.len() >= self.max_cache_size {
|
||
self.evict_lru(&mut cache);
|
||
}
|
||
|
||
let cached = CachedValue {
|
||
value,
|
||
expiry: Self::current_timestamp() + ttl,
|
||
access_count: 0,
|
||
};
|
||
|
||
cache.insert(key, cached);
|
||
}
|
||
|
||
/// 移除最少使用的缓存项
|
||
fn evict_lru(&self, cache: &mut HashMap<String, CachedValue>) {
|
||
if let Some((key, _)) = cache
|
||
.iter()
|
||
.min_by_key(|(_, v)| v.access_count)
|
||
{
|
||
let key = key.clone();
|
||
cache.remove(&key);
|
||
}
|
||
}
|
||
|
||
/// 清空缓存
|
||
pub fn clear(&self) {
|
||
self.cache.write().unwrap().clear();
|
||
}
|
||
|
||
/// 获取缓存统计
|
||
pub fn get_cache_stats(&self) -> CacheStatistics {
|
||
let hits = *self.cache_hits.lock().unwrap();
|
||
let misses = *self.cache_misses.lock().unwrap();
|
||
let total = hits + misses;
|
||
let hit_rate = if total > 0 {
|
||
(hits as f64 / total as f64) * 100.0
|
||
} else {
|
||
0.0
|
||
};
|
||
|
||
CacheStatistics {
|
||
cache_size: self.cache.read().unwrap().len(),
|
||
max_cache_size: self.max_cache_size,
|
||
cache_hits: hits,
|
||
cache_misses: misses,
|
||
hit_rate,
|
||
}
|
||
}
|
||
|
||
/// 获取当前时间戳
|
||
fn current_timestamp() -> u64 {
|
||
use std::time::{SystemTime, UNIX_EPOCH};
|
||
SystemTime::now()
|
||
.duration_since(UNIX_EPOCH)
|
||
.unwrap()
|
||
.as_secs()
|
||
}
|
||
}
|
||
|
||
/// 缓存统计
|
||
#[derive(Debug, Clone)]
|
||
pub struct CacheStatistics {
|
||
/// 当前缓存大小
|
||
pub cache_size: usize,
|
||
/// 最大缓存大小
|
||
pub max_cache_size: usize,
|
||
/// 缓存命中次数
|
||
pub cache_hits: u64,
|
||
/// 缓存未命中次数
|
||
pub cache_misses: u64,
|
||
/// 命中率(百分比)
|
||
pub hit_rate: f64,
|
||
}
|
||
|
||
/// 计算优化器
|
||
#[derive(Debug)]
|
||
pub struct ComputationOptimizer {
|
||
/// 结果缓存
|
||
result_cache: Arc<RwLock<HashMap<String, ComputationResult>>>,
|
||
}
|
||
|
||
/// 计算结果
|
||
#[derive(Debug, Clone)]
|
||
struct ComputationResult {
|
||
/// 结果
|
||
result: Vec<u8>,
|
||
/// 计算时间(毫秒)
|
||
computation_time_ms: u64,
|
||
}
|
||
|
||
impl ComputationOptimizer {
|
||
/// 创建新的计算优化器
|
||
pub fn new() -> Self {
|
||
Self {
|
||
result_cache: Arc::new(RwLock::new(HashMap::new())),
|
||
}
|
||
}
|
||
|
||
/// 执行计算(带缓存)
|
||
pub fn compute<F>(&self, key: &str, computation: F) -> Vec<u8>
|
||
where
|
||
F: FnOnce() -> Vec<u8>,
|
||
{
|
||
// 检查缓存
|
||
{
|
||
let cache = self.result_cache.read().unwrap();
|
||
if let Some(cached) = cache.get(key) {
|
||
return cached.result.clone();
|
||
}
|
||
}
|
||
|
||
// 执行计算
|
||
let start = std::time::Instant::now();
|
||
let result = computation();
|
||
let computation_time_ms = start.elapsed().as_millis() as u64;
|
||
|
||
// 缓存结果
|
||
{
|
||
let mut cache = self.result_cache.write().unwrap();
|
||
cache.insert(
|
||
key.to_string(),
|
||
ComputationResult {
|
||
result: result.clone(),
|
||
computation_time_ms,
|
||
},
|
||
);
|
||
}
|
||
|
||
result
|
||
}
|
||
|
||
/// 清空计算缓存
|
||
pub fn clear(&self) {
|
||
self.result_cache.write().unwrap().clear();
|
||
}
|
||
}
|
||
|
||
/// Gas优化器
|
||
#[derive(Debug)]
|
||
pub struct GasOptimizer {
|
||
/// Gas价格
|
||
gas_price: u64,
|
||
/// Gas使用统计
|
||
gas_usage: Arc<Mutex<HashMap<String, u64>>>,
|
||
}
|
||
|
||
impl GasOptimizer {
|
||
/// 创建新的Gas优化器
|
||
pub fn new(gas_price: u64) -> Self {
|
||
Self {
|
||
gas_price,
|
||
gas_usage: Arc::new(Mutex::new(HashMap::new())),
|
||
}
|
||
}
|
||
|
||
/// 估算操作的Gas成本
|
||
pub fn estimate_gas(&self, operation: &str) -> u64 {
|
||
match operation {
|
||
"transfer" => 21000,
|
||
"mint" => 50000,
|
||
"burn" => 30000,
|
||
"create_partition" => 100000,
|
||
"close_partition" => 50000,
|
||
"authorize_operator" => 40000,
|
||
"revoke_operator" => 30000,
|
||
"batch_transfer" => 100000, // 基础成本,每个转账额外21000
|
||
"batch_mint" => 150000, // 基础成本,每个铸造额外50000
|
||
"batch_burn" => 100000, // 基础成本,每个销毁额外30000
|
||
_ => 10000,
|
||
}
|
||
}
|
||
|
||
/// 估算批量操作的Gas成本
|
||
pub fn estimate_batch_gas(&self, operation: &str, count: usize) -> u64 {
|
||
let base_gas = self.estimate_gas(operation);
|
||
let per_item_gas = match operation {
|
||
"batch_transfer" => 21000,
|
||
"batch_mint" => 50000,
|
||
"batch_burn" => 30000,
|
||
_ => 0,
|
||
};
|
||
|
||
base_gas + (per_item_gas * count as u64)
|
||
}
|
||
|
||
/// 记录Gas使用
|
||
pub fn record_gas_usage(&self, operation: String, gas_used: u64) {
|
||
let mut usage = self.gas_usage.lock().unwrap();
|
||
*usage.entry(operation).or_insert(0) += gas_used;
|
||
}
|
||
|
||
/// 获取Gas使用统计
|
||
pub fn get_gas_statistics(&self) -> GasStatistics {
|
||
let usage = self.gas_usage.lock().unwrap();
|
||
let total_gas = usage.values().sum();
|
||
let total_cost = total_gas * self.gas_price;
|
||
|
||
GasStatistics {
|
||
total_gas_used: total_gas,
|
||
gas_price: self.gas_price,
|
||
total_cost,
|
||
operations: usage.clone(),
|
||
}
|
||
}
|
||
|
||
/// 优化建议
|
||
pub fn get_optimization_suggestions(&self) -> Vec<String> {
|
||
let mut suggestions = Vec::new();
|
||
let usage = self.gas_usage.lock().unwrap();
|
||
|
||
// 检查批量操作使用情况
|
||
let batch_operations = ["batch_transfer", "batch_mint", "batch_burn"];
|
||
for op in &batch_operations {
|
||
if usage.get(*op).unwrap_or(&0) == &0 {
|
||
suggestions.push(format!(
|
||
"Consider using {} for multiple operations to save gas",
|
||
op
|
||
));
|
||
}
|
||
}
|
||
|
||
// 检查高Gas操作
|
||
for (op, gas) in usage.iter() {
|
||
if *gas > 1000000 {
|
||
suggestions.push(format!(
|
||
"Operation '{}' has high gas usage ({}), consider optimization",
|
||
op, gas
|
||
));
|
||
}
|
||
}
|
||
|
||
suggestions
|
||
}
|
||
}
|
||
|
||
/// Gas统计
|
||
#[derive(Debug, Clone)]
|
||
pub struct GasStatistics {
|
||
/// 总Gas使用量
|
||
pub total_gas_used: u64,
|
||
/// Gas价格
|
||
pub gas_price: u64,
|
||
/// 总成本
|
||
pub total_cost: u64,
|
||
/// 各操作的Gas使用量
|
||
pub operations: HashMap<String, u64>,
|
||
}
|
||
|
||
/// 并发处理器
|
||
#[derive(Debug)]
|
||
pub struct ConcurrentProcessor {
|
||
/// 工作线程数
|
||
worker_count: usize,
|
||
}
|
||
|
||
impl ConcurrentProcessor {
|
||
/// 创建新的并发处理器
|
||
pub fn new(worker_count: usize) -> Self {
|
||
Self { worker_count }
|
||
}
|
||
|
||
/// 并发处理批量任务
|
||
pub fn process_batch<T, F, R>(&self, items: Vec<T>, processor: F) -> Vec<R>
|
||
where
|
||
T: Send + Clone + 'static,
|
||
F: Fn(T) -> R + Send + Sync + 'static,
|
||
R: Send + 'static,
|
||
{
|
||
use std::sync::mpsc;
|
||
use std::thread;
|
||
|
||
let (tx, rx) = mpsc::channel();
|
||
let processor = Arc::new(processor);
|
||
let chunk_size = (items.len() + self.worker_count - 1) / self.worker_count;
|
||
|
||
let mut handles = Vec::new();
|
||
|
||
for chunk in items.chunks(chunk_size) {
|
||
let tx = tx.clone();
|
||
let processor = Arc::clone(&processor);
|
||
let chunk = chunk.to_vec();
|
||
|
||
let handle = thread::spawn(move || {
|
||
for item in chunk {
|
||
let result = processor(item);
|
||
tx.send(result).unwrap();
|
||
}
|
||
});
|
||
|
||
handles.push(handle);
|
||
}
|
||
|
||
drop(tx);
|
||
|
||
// 等待所有线程完成
|
||
for handle in handles {
|
||
handle.join().unwrap();
|
||
}
|
||
|
||
// 收集结果
|
||
rx.iter().collect()
|
||
}
|
||
}
|
||
|
||
impl Default for ComputationOptimizer {
|
||
fn default() -> Self {
|
||
Self::new()
|
||
}
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
#[test]
|
||
fn test_storage_optimizer_cache() {
|
||
let optimizer = StorageOptimizer::new(100);
|
||
|
||
// 设置缓存
|
||
optimizer.set("key1".to_string(), vec![1, 2, 3], 60);
|
||
|
||
// 获取缓存
|
||
let value = optimizer.get("key1");
|
||
assert_eq!(value, Some(vec![1, 2, 3]));
|
||
|
||
// 获取不存在的键
|
||
let value = optimizer.get("key2");
|
||
assert_eq!(value, None);
|
||
}
|
||
|
||
#[test]
|
||
fn test_storage_optimizer_stats() {
|
||
let optimizer = StorageOptimizer::new(100);
|
||
|
||
optimizer.set("key1".to_string(), vec![1, 2, 3], 60);
|
||
optimizer.get("key1");
|
||
optimizer.get("key2");
|
||
|
||
let stats = optimizer.get_cache_stats();
|
||
assert_eq!(stats.cache_hits, 1);
|
||
assert_eq!(stats.cache_misses, 1);
|
||
assert_eq!(stats.hit_rate, 50.0);
|
||
}
|
||
|
||
#[test]
|
||
fn test_computation_optimizer() {
|
||
let optimizer = ComputationOptimizer::new();
|
||
|
||
let mut call_count = 0;
|
||
let computation = || {
|
||
call_count += 1;
|
||
vec![1, 2, 3]
|
||
};
|
||
|
||
// 第一次调用,执行计算
|
||
let result1 = optimizer.compute("test", computation);
|
||
assert_eq!(result1, vec![1, 2, 3]);
|
||
|
||
// 第二次调用,使用缓存
|
||
let result2 = optimizer.compute("test", || vec![4, 5, 6]);
|
||
assert_eq!(result2, vec![1, 2, 3]); // 应该返回缓存的结果
|
||
}
|
||
|
||
#[test]
|
||
fn test_gas_optimizer_estimate() {
|
||
let optimizer = GasOptimizer::new(100);
|
||
|
||
assert_eq!(optimizer.estimate_gas("transfer"), 21000);
|
||
assert_eq!(optimizer.estimate_gas("mint"), 50000);
|
||
assert_eq!(optimizer.estimate_gas("burn"), 30000);
|
||
}
|
||
|
||
#[test]
|
||
fn test_gas_optimizer_batch_estimate() {
|
||
let optimizer = GasOptimizer::new(100);
|
||
|
||
// 批量转账10笔
|
||
let gas = optimizer.estimate_batch_gas("batch_transfer", 10);
|
||
assert_eq!(gas, 100000 + 21000 * 10);
|
||
}
|
||
|
||
#[test]
|
||
fn test_gas_optimizer_statistics() {
|
||
let optimizer = GasOptimizer::new(100);
|
||
|
||
optimizer.record_gas_usage("transfer".to_string(), 21000);
|
||
optimizer.record_gas_usage("mint".to_string(), 50000);
|
||
|
||
let stats = optimizer.get_gas_statistics();
|
||
assert_eq!(stats.total_gas_used, 71000);
|
||
assert_eq!(stats.total_cost, 7100000);
|
||
}
|
||
|
||
#[test]
|
||
fn test_gas_optimizer_suggestions() {
|
||
let optimizer = GasOptimizer::new(100);
|
||
|
||
// 记录一些操作
|
||
optimizer.record_gas_usage("transfer".to_string(), 21000);
|
||
|
||
let suggestions = optimizer.get_optimization_suggestions();
|
||
assert!(!suggestions.is_empty());
|
||
}
|
||
|
||
#[test]
|
||
fn test_concurrent_processor() {
|
||
let processor = ConcurrentProcessor::new(4);
|
||
|
||
let items: Vec<u32> = (0..100).collect();
|
||
let results = processor.process_batch(items, |x| x * 2);
|
||
|
||
assert_eq!(results.len(), 100);
|
||
// 注意:由于并发处理,结果顺序可能不同
|
||
}
|
||
|
||
#[test]
|
||
fn test_cache_eviction() {
|
||
let optimizer = StorageOptimizer::new(2);
|
||
|
||
// 添加3个项,应该触发LRU驱逐
|
||
optimizer.set("key1".to_string(), vec![1], 60);
|
||
optimizer.set("key2".to_string(), vec![2], 60);
|
||
optimizer.set("key3".to_string(), vec![3], 60);
|
||
|
||
// 缓存大小应该是2
|
||
let stats = optimizer.get_cache_stats();
|
||
assert_eq!(stats.cache_size, 2);
|
||
}
|
||
|
||
#[test]
|
||
fn test_cache_expiry() {
|
||
let optimizer = StorageOptimizer::new(100);
|
||
|
||
// 设置一个立即过期的缓存
|
||
optimizer.set("key1".to_string(), vec![1, 2, 3], 0);
|
||
|
||
// 等待1秒
|
||
std::thread::sleep(std::time::Duration::from_secs(1));
|
||
|
||
// 应该无法获取(已过期)
|
||
let value = optimizer.get("key1");
|
||
assert_eq!(value, None);
|
||
}
|
||
}
|