NAC_Blockchain/nac-udm/src/l1_protocol/state_shard_optimization.rs

562 lines
16 KiB
Rust
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

///! 状态分片优化模块
///!
///! 优化分片状态存储和访问性能
///!
///! **NAC原生设计原则**
///! - 使用Asset资产不是Token
///! - 使用Certificate证书不是Contract
///! - 使用SHA3-384哈希不是SHA256/Keccak256
///! - 通过CBPP共识协调
use crate::primitives::{Address, Hash};
use std::collections::HashMap;
use serde::{Deserialize, Serialize};
/// 状态分片优化器
#[derive(Debug, Clone)]
/// StateShardOptimizer
pub struct StateShardOptimizer {
/// 分片ID
shard_id: u64,
/// 状态缓存
state_cache: HashMap<Hash, StateEntry>,
/// 热点账户追踪
hot_accounts: HashMap<Address, HotAccountStats>,
/// 冷数据归档阈值(秒)
cold_threshold: u64,
/// 缓存大小限制(字节)
max_cache_size: u64,
/// 当前缓存大小
current_cache_size: u64,
/// 优化统计
stats: OptimizationStats,
}
/// 状态条目
#[derive(Debug, Clone, Serialize, Deserialize)]
/// StateEntry
pub struct StateEntry {
/// 状态键
pub key: Hash,
/// 状态值
pub value: Vec<u8>,
/// 最后访问时间
pub last_access: u64,
/// 访问次数
pub access_count: u64,
/// 是否为热点数据
pub is_hot: bool,
/// 数据大小(字节)
pub size: u64,
}
impl StateEntry {
/// 创建新的状态条目
pub fn new(key: Hash, value: Vec<u8>, timestamp: u64) -> Self {
let size = value.len() as u64;
Self {
key,
value,
last_access: timestamp,
access_count: 1,
is_hot: false,
size,
}
}
/// 更新访问信息
pub fn update_access(&mut self, timestamp: u64) {
self.last_access = timestamp;
self.access_count += 1;
// 访问次数超过阈值标记为热点
if self.access_count > 100 {
self.is_hot = true;
}
}
/// 检查是否为冷数据
pub fn is_cold(&self, current_time: u64, threshold: u64) -> bool {
current_time - self.last_access > threshold
}
}
/// 热点账户统计
#[derive(Debug, Clone, Serialize, Deserialize)]
/// HotAccountStats
pub struct HotAccountStats {
/// 账户地址
pub address: Address,
/// 读取次数
pub read_count: u64,
/// 写入次数
pub write_count: u64,
/// 最后活动时间
pub last_activity: u64,
/// 平均交易大小
pub avg_tx_size: u64,
/// 是否为高频账户
pub is_high_frequency: bool,
}
impl HotAccountStats {
/// 创建新的热点账户统计
pub fn new(address: Address, timestamp: u64) -> Self {
Self {
address,
read_count: 0,
write_count: 0,
last_activity: timestamp,
avg_tx_size: 0,
is_high_frequency: false,
}
}
/// 记录读取操作
pub fn record_read(&mut self, timestamp: u64) {
self.read_count += 1;
self.last_activity = timestamp;
self.update_frequency();
}
/// 记录写入操作
pub fn record_write(&mut self, timestamp: u64, tx_size: u64) {
self.write_count += 1;
self.last_activity = timestamp;
// 更新平均交易大小
let total_count = self.read_count + self.write_count;
self.avg_tx_size = (self.avg_tx_size * (total_count - 1) + tx_size) / total_count;
self.update_frequency();
}
/// 更新频率标记
fn update_frequency(&mut self) {
// 读写总次数超过1000标记为高频
if self.read_count + self.write_count > 1000 {
self.is_high_frequency = true;
}
}
}
/// 优化统计
#[derive(Debug, Clone, Serialize, Deserialize, Default)]
/// OptimizationStats
pub struct OptimizationStats {
/// 缓存命中次数
pub cache_hits: u64,
/// 缓存未命中次数
pub cache_misses: u64,
/// 冷数据归档次数
pub cold_data_archived: u64,
/// 热点数据提升次数
pub hot_data_promoted: u64,
/// 缓存驱逐次数
pub cache_evictions: u64,
/// 总状态访问次数
pub total_accesses: u64,
}
impl OptimizationStats {
/// 计算缓存命中率
pub fn cache_hit_rate(&self) -> f64 {
if self.total_accesses == 0 {
return 0.0;
}
self.cache_hits as f64 / self.total_accesses as f64
}
}
impl StateShardOptimizer {
/// 创建新的状态分片优化器
pub fn new(shard_id: u64, cold_threshold: u64, max_cache_size: u64) -> Self {
Self {
shard_id,
state_cache: HashMap::new(),
hot_accounts: HashMap::new(),
cold_threshold,
max_cache_size,
current_cache_size: 0,
stats: OptimizationStats::default(),
}
}
/// 读取状态
pub fn read_state(&mut self, key: &Hash, current_time: u64) -> Option<Vec<u8>> {
self.stats.total_accesses += 1;
if let Some(entry) = self.state_cache.get_mut(key) {
// 缓存命中
self.stats.cache_hits += 1;
entry.update_access(current_time);
Some(entry.value.clone())
} else {
// 缓存未命中
self.stats.cache_misses += 1;
None
}
}
/// 写入状态
pub fn write_state(&mut self, key: Hash, value: Vec<u8>, current_time: u64) -> Result<(), String> {
let entry_size = value.len() as u64;
// 检查缓存大小限制
if self.current_cache_size + entry_size > self.max_cache_size {
// 驱逐冷数据
self.evict_cold_data(current_time)?;
}
// 创建或更新状态条目
if let Some(existing) = self.state_cache.get_mut(&key) {
self.current_cache_size -= existing.size;
existing.value = value;
existing.size = entry_size;
existing.update_access(current_time);
self.current_cache_size += entry_size;
} else {
let entry = StateEntry::new(key.clone(), value, current_time);
self.state_cache.insert(key, entry);
self.current_cache_size += entry_size;
}
Ok(())
}
/// 驱逐冷数据
pub fn evict_cold_data(&mut self, current_time: u64) -> Result<(), String> {
let mut cold_keys = Vec::new();
// 查找冷数据
for (key, entry) in &self.state_cache {
if entry.is_cold(current_time, self.cold_threshold) && !entry.is_hot {
cold_keys.push(key.clone());
}
}
if cold_keys.is_empty() {
return Err("No cold data to evict".to_string());
}
// 驱逐冷数据
for key in cold_keys {
if let Some(entry) = self.state_cache.remove(&key) {
self.current_cache_size -= entry.size;
self.stats.cache_evictions += 1;
self.stats.cold_data_archived += 1;
}
}
Ok(())
}
/// 提升热点数据
pub fn promote_hot_data(&mut self, key: &Hash) -> Result<(), String> {
if let Some(entry) = self.state_cache.get_mut(key) {
if !entry.is_hot {
entry.is_hot = true;
self.stats.hot_data_promoted += 1;
}
Ok(())
} else {
Err("State entry not found".to_string())
}
}
/// 记录账户活动
pub fn record_account_activity(
&mut self,
address: Address,
is_write: bool,
tx_size: u64,
timestamp: u64,
) {
let stats = self.hot_accounts
.entry(address.clone())
.or_insert_with(|| HotAccountStats::new(address, timestamp));
if is_write {
stats.record_write(timestamp, tx_size);
} else {
stats.record_read(timestamp);
}
}
/// 获取热点账户列表
pub fn get_hot_accounts(&self) -> Vec<Address> {
self.hot_accounts
.values()
.filter(|stats| stats.is_high_frequency)
.map(|stats| stats.address.clone())
.collect()
}
/// 获取优化统计
pub fn get_stats(&self) -> OptimizationStats {
self.stats.clone()
}
/// 获取缓存使用率
pub fn get_cache_usage(&self) -> f64 {
if self.max_cache_size == 0 {
return 0.0;
}
self.current_cache_size as f64 / self.max_cache_size as f64
}
/// 清理过期数据
pub fn cleanup_expired(&mut self, current_time: u64) -> usize {
let mut expired_keys = Vec::new();
// 查找过期数据超过冷数据阈值的2倍
let expiry_threshold = self.cold_threshold * 2;
for (key, entry) in &self.state_cache {
if current_time - entry.last_access > expiry_threshold {
expired_keys.push(key.clone());
}
}
let count = expired_keys.len();
// 删除过期数据
for key in expired_keys {
if let Some(entry) = self.state_cache.remove(&key) {
self.current_cache_size -= entry.size;
}
}
count
}
/// 优化分片状态
pub fn optimize(&mut self, current_time: u64) -> Result<OptimizationReport, String> {
let initial_cache_size = self.current_cache_size;
let initial_entry_count = self.state_cache.len();
// 1. 清理过期数据
let expired_count = self.cleanup_expired(current_time);
// 2. 驱逐冷数据如果缓存使用率超过80%
let evicted_count = if self.get_cache_usage() > 0.8 {
let before = self.state_cache.len();
self.evict_cold_data(current_time)?;
before - self.state_cache.len()
} else {
0
};
// 3. 提升热点数据
let hot_keys: Vec<Hash> = self.state_cache
.iter()
.filter(|(_, entry)| entry.access_count > 50 && !entry.is_hot)
.map(|(key, _)| key.clone())
.collect();
for key in &hot_keys {
let _ = self.promote_hot_data(key);
}
Ok(OptimizationReport {
shard_id: self.shard_id,
expired_count,
evicted_count,
promoted_count: hot_keys.len(),
space_freed: initial_cache_size - self.current_cache_size,
entries_before: initial_entry_count,
entries_after: self.state_cache.len(),
cache_hit_rate: self.stats.cache_hit_rate(),
})
}
}
/// 优化报告
#[derive(Debug, Clone, Serialize, Deserialize)]
/// OptimizationReport
pub struct OptimizationReport {
/// 分片ID
pub shard_id: u64,
/// 清理的过期数据数量
pub expired_count: usize,
/// 驱逐的冷数据数量
pub evicted_count: usize,
/// 提升的热点数据数量
pub promoted_count: usize,
/// 释放的空间(字节)
pub space_freed: u64,
/// 优化前条目数
pub entries_before: usize,
/// 优化后条目数
pub entries_after: usize,
/// 缓存命中率
pub cache_hit_rate: f64,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_state_entry_creation() {
let key = Hash::from_slice(&[1u8; 32]).unwrap();
let value = vec![1, 2, 3, 4];
let entry = StateEntry::new(key, value.clone(), 1000);
assert_eq!(entry.value, value);
assert_eq!(entry.last_access, 1000);
assert_eq!(entry.access_count, 1);
assert!(!entry.is_hot);
assert_eq!(entry.size, 4);
}
#[test]
fn test_state_entry_hot_promotion() {
let key = Hash::from_slice(&[1u8; 32]).unwrap();
let value = vec![1, 2, 3];
let mut entry = StateEntry::new(key, value, 1000);
// 访问101次应该变为热点
for i in 0..101 {
entry.update_access(1000 + i);
}
assert!(entry.is_hot);
assert_eq!(entry.access_count, 102); // 初始1次 + 101次
}
#[test]
fn test_state_entry_cold_detection() {
let key = Hash::from_slice(&[1u8; 32]).unwrap();
let value = vec![1, 2, 3];
let entry = StateEntry::new(key, value, 1000);
// 在阈值内不是冷数据
assert!(!entry.is_cold(1500, 1000));
// 超过阈值是冷数据
assert!(entry.is_cold(2001, 1000));
}
#[test]
fn test_optimizer_read_write() {
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
let key = Hash::from_slice(&[1u8; 32]).unwrap();
let value = vec![1, 2, 3, 4];
// 写入状态
assert!(optimizer.write_state(key.clone(), value.clone(), 1000).is_ok());
// 读取状态
let read_value = optimizer.read_state(&key, 1001);
assert_eq!(read_value, Some(value));
// 验证统计
assert_eq!(optimizer.stats.cache_hits, 1);
assert_eq!(optimizer.stats.total_accesses, 1);
}
#[test]
fn test_optimizer_cache_miss() {
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
let key = Hash::from_slice(&[1u8; 32]).unwrap();
// 读取不存在的状态
let result = optimizer.read_state(&key, 1000);
assert!(result.is_none());
// 验证统计
assert_eq!(optimizer.stats.cache_misses, 1);
assert_eq!(optimizer.stats.total_accesses, 1);
}
#[test]
fn test_optimizer_evict_cold_data() {
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024);
// 写入一些数据
for i in 0..5 {
let key = Hash::from_slice(&[i; 32]).unwrap();
let value = vec![i; 100];
optimizer.write_state(key, value, 1000 + i as u64).unwrap();
}
// 等待一段时间后驱逐冷数据
assert!(optimizer.evict_cold_data(3000).is_ok());
// 验证统计
assert!(optimizer.stats.cold_data_archived > 0);
}
#[test]
fn test_optimizer_hot_account_tracking() {
let mut optimizer = StateShardOptimizer::new(1, 3600, 1024 * 1024);
let address = Address::from_slice(&[1u8; 32]).unwrap();
// 记录大量活动
for i in 0..1001 {
optimizer.record_account_activity(address.clone(), i % 2 == 0, 100, 1000 + i);
}
// 验证热点账户
let hot_accounts = optimizer.get_hot_accounts();
assert_eq!(hot_accounts.len(), 1);
assert_eq!(hot_accounts[0], address);
}
#[test]
fn test_optimizer_cache_usage() {
let mut optimizer = StateShardOptimizer::new(1, 3600, 1000);
// 写入500字节数据
let key = Hash::from_slice(&[1u8; 32]).unwrap();
let value = vec![1u8; 500];
optimizer.write_state(key, value, 1000).unwrap();
// 验证缓存使用率
assert_eq!(optimizer.get_cache_usage(), 0.5);
}
#[test]
fn test_optimizer_cleanup_expired() {
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024 * 1024);
// 写入一些数据
for i in 0..5 {
let key = Hash::from_slice(&[i; 32]).unwrap();
let value = vec![i; 10];
optimizer.write_state(key, value, 1000).unwrap();
}
// 清理过期数据超过2000秒
let expired = optimizer.cleanup_expired(4000);
assert_eq!(expired, 5);
}
#[test]
fn test_optimizer_full_optimization() {
let mut optimizer = StateShardOptimizer::new(1, 1000, 1024 * 1024);
// 写入一些数据
for i in 0..10 {
let key = Hash::from_slice(&[i; 32]).unwrap();
let value = vec![i; 100];
optimizer.write_state(key, value, 1000 + i as u64).unwrap();
}
// 访问部分数据使其成为热点但不超过100次避免自动标记为hot
for i in 0..3 {
let key = Hash::from_slice(&[i; 32]).unwrap();
for _ in 0..50 {
optimizer.read_state(&key, 2000);
}
}
// 执行优化
let report = optimizer.optimize(4000).unwrap();
assert_eq!(report.shard_id, 1);
assert!(report.promoted_count > 0);
assert!(report.cache_hit_rate > 0.0);
}
}