提交qiming-mcp-proxy

This commit is contained in:
Codex
2026-06-01 13:03:20 +08:00
parent 9e9486b7c2
commit afb3d9f4e6
394 changed files with 124494 additions and 0 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,704 @@
//! 并发优化器
//!
//! 提供任务队列管理、工作线程池和负载均衡功能
#![allow(dead_code)]
use futures::future::BoxFuture;
use std::collections::VecDeque;
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::time::{Duration, Instant};
use tokio::sync::{Mutex, RwLock, Semaphore, mpsc, oneshot};
use tokio::task::JoinHandle;
use uuid::Uuid;
use super::{ConcurrencyConfig, PerformanceOptimizable};
use crate::config::AppConfig;
use crate::error::AppError;
/// 并发优化器
pub struct ConcurrencyOptimizer {
config: ConcurrencyConfig,
task_queue: Arc<TaskQueue>,
worker_pool: Arc<WorkerPool>,
load_balancer: Arc<LoadBalancer>,
semaphore: Arc<Semaphore>,
stats: Arc<ConcurrencyStats>,
}
impl ConcurrencyOptimizer {
/// 创建新的并发优化器
pub async fn new(_config: &AppConfig) -> Result<Self, AppError> {
let concurrency_config = ConcurrencyConfig::default(); // 从配置中获取
let task_queue = Arc::new(TaskQueue::new(concurrency_config.task_queue_size));
let worker_pool = Arc::new(WorkerPool::new(concurrency_config.worker_threads).await?);
let load_balancer = Arc::new(LoadBalancer::new());
let semaphore = Arc::new(Semaphore::new(concurrency_config.max_concurrent_tasks));
let stats = Arc::new(ConcurrencyStats::new());
Ok(Self {
config: concurrency_config,
task_queue,
worker_pool,
load_balancer,
semaphore,
stats,
})
}
/// 提交任务
pub async fn submit_task<F, T>(&self, task: F) -> Result<TaskHandle<T>, AppError>
where
F: FnOnce() -> BoxFuture<'static, Result<T, AppError>> + Send + 'static,
T: Send + 'static,
{
// 获取信号量许可
let permit = self
.semaphore
.clone()
.acquire_owned()
.await
.map_err(|_| AppError::Config("Concurrency limit exceeded".to_string()))?;
// 创建任务
let task_id = Uuid::new_v4().to_string();
let (result_tx, result_rx) = oneshot::channel();
let concurrent_task = ConcurrentTask {
id: task_id.clone(),
task: Box::new(move || {
Box::pin(async move {
let result = task().await;
let _ = result_tx.send(result);
})
}),
priority: TaskPriority::Normal,
submitted_at: Instant::now(),
timeout: self.config.task_timeout,
};
// 提交到队列
self.task_queue.enqueue(concurrent_task).await?;
// 更新统计
self.stats.record_task_submitted().await;
// 通知工作池有新任务
self.worker_pool.notify_new_task().await;
Ok(TaskHandle {
id: task_id,
result_rx,
_permit: permit,
})
}
/// 提交高优先级任务
pub async fn submit_priority_task<F, T>(&self, task: F) -> Result<TaskHandle<T>, AppError>
where
F: FnOnce() -> BoxFuture<'static, Result<T, AppError>> + Send + 'static,
T: Send + 'static,
{
let permit = self
.semaphore
.clone()
.acquire_owned()
.await
.map_err(|_| AppError::Config("Concurrency limit exceeded".to_string()))?;
let task_id = Uuid::new_v4().to_string();
let (result_tx, result_rx) = oneshot::channel();
let concurrent_task = ConcurrentTask {
id: task_id.clone(),
task: Box::new(move || {
Box::pin(async move {
let result = task().await;
let _ = result_tx.send(result);
})
}),
priority: TaskPriority::High,
submitted_at: Instant::now(),
timeout: self.config.task_timeout,
};
self.task_queue.enqueue_priority(concurrent_task).await?;
self.stats.record_priority_task_submitted().await;
self.worker_pool.notify_new_task().await;
Ok(TaskHandle {
id: task_id,
result_rx,
_permit: permit,
})
}
/// 获取队列状态
pub async fn get_queue_status(&self) -> QueueStatus {
QueueStatus {
pending_tasks: self.task_queue.pending_count().await,
active_tasks: self.worker_pool.active_count().await,
available_workers: self.worker_pool.available_count().await,
queue_capacity: self.config.task_queue_size,
}
}
/// 获取并发统计
pub async fn get_concurrency_stats(&self) -> Result<ConcurrencyStats, AppError> {
Ok(self.stats.clone_stats().await)
}
/// 调整并发参数
pub async fn adjust_concurrency(&self, new_max_concurrent: usize) -> Result<(), AppError> {
// 动态调整信号量
let current_permits = self.semaphore.available_permits();
if new_max_concurrent > current_permits {
self.semaphore
.add_permits(new_max_concurrent - current_permits);
}
self.stats
.record_concurrency_adjustment(new_max_concurrent)
.await;
Ok(())
}
}
#[async_trait::async_trait]
impl PerformanceOptimizable for ConcurrencyOptimizer {
async fn optimize(&self) -> Result<(), AppError> {
// 优化任务队列
self.task_queue.optimize().await?;
// 优化工作池
self.worker_pool.optimize().await?;
// 执行负载均衡
self.load_balancer.balance(&self.worker_pool).await?;
Ok(())
}
async fn get_stats(&self) -> Result<serde_json::Value, AppError> {
let stats = self.get_concurrency_stats().await?;
let queue_status = self.get_queue_status().await;
Ok(serde_json::json!({
"stats": stats,
"queue_status": queue_status
}))
}
async fn reset_stats(&self) -> Result<(), AppError> {
self.stats.reset().await;
Ok(())
}
}
/// 任务队列
pub struct TaskQueue {
normal_queue: Arc<Mutex<VecDeque<ConcurrentTask>>>,
priority_queue: Arc<Mutex<VecDeque<ConcurrentTask>>>,
max_size: usize,
stats: Arc<QueueStats>,
}
impl TaskQueue {
pub fn new(max_size: usize) -> Self {
Self {
normal_queue: Arc::new(Mutex::new(VecDeque::new())),
priority_queue: Arc::new(Mutex::new(VecDeque::new())),
max_size,
stats: Arc::new(QueueStats::new()),
}
}
async fn enqueue(&self, task: ConcurrentTask) -> Result<(), AppError> {
let mut queue = self.normal_queue.lock().await;
if queue.len() >= self.max_size {
return Err(AppError::Config("Queue is full".to_string()));
}
queue.push_back(task);
self.stats.record_enqueue().await;
Ok(())
}
async fn enqueue_priority(&self, task: ConcurrentTask) -> Result<(), AppError> {
let mut queue = self.priority_queue.lock().await;
if queue.len() >= self.max_size / 2 {
// 优先级队列占用一半容量
return Err(AppError::Config("Priority queue is full".to_string()));
}
queue.push_back(task);
self.stats.record_priority_enqueue().await;
Ok(())
}
async fn dequeue(&self) -> Option<ConcurrentTask> {
// 优先处理高优先级任务
{
let mut priority_queue = self.priority_queue.lock().await;
if let Some(task) = priority_queue.pop_front() {
self.stats.record_priority_dequeue().await;
return Some(task);
}
}
// 处理普通任务
let mut normal_queue = self.normal_queue.lock().await;
if let Some(task) = normal_queue.pop_front() {
self.stats.record_dequeue().await;
return Some(task);
}
None
}
pub async fn pending_count(&self) -> usize {
let normal_count = self.normal_queue.lock().await.len();
let priority_count = self.priority_queue.lock().await.len();
normal_count + priority_count
}
pub async fn optimize(&self) -> Result<(), AppError> {
// 清理超时任务
let now = Instant::now();
{
let mut normal_queue = self.normal_queue.lock().await;
normal_queue.retain(|task| now.duration_since(task.submitted_at) < task.timeout);
}
{
let mut priority_queue = self.priority_queue.lock().await;
priority_queue.retain(|task| now.duration_since(task.submitted_at) < task.timeout);
}
self.stats.record_cleanup().await;
Ok(())
}
}
/// 工作线程池
pub struct WorkerPool {
workers: Vec<Worker>,
task_sender: mpsc::UnboundedSender<WorkerMessage>,
stats: Arc<WorkerStats>,
}
impl WorkerPool {
pub async fn new(worker_count: usize) -> Result<Self, AppError> {
let (task_sender, task_receiver) = mpsc::unbounded_channel();
let task_receiver = Arc::new(Mutex::new(task_receiver));
let stats = Arc::new(WorkerStats::new());
let mut workers = Vec::new();
for i in 0..worker_count {
let worker = Worker::new(i, task_receiver.clone(), stats.clone()).await?;
workers.push(worker);
}
Ok(Self {
workers,
task_sender,
stats,
})
}
pub async fn notify_new_task(&self) {
let _ = self.task_sender.send(WorkerMessage::NewTask);
}
pub async fn active_count(&self) -> usize {
self.stats.active_workers().await
}
pub async fn available_count(&self) -> usize {
self.workers.len() - self.active_count().await
}
pub async fn optimize(&self) -> Result<(), AppError> {
// 检查工作线程健康状态
for worker in &self.workers {
if !worker.is_healthy().await {
worker.restart().await?;
}
}
Ok(())
}
}
/// 工作线程
pub struct Worker {
id: usize,
handle: JoinHandle<()>,
is_active: Arc<AtomicUsize>,
last_activity: Arc<RwLock<Instant>>,
}
impl Worker {
async fn new(
id: usize,
task_receiver: Arc<Mutex<mpsc::UnboundedReceiver<WorkerMessage>>>,
stats: Arc<WorkerStats>,
) -> Result<Self, AppError> {
let is_active = Arc::new(AtomicUsize::new(0));
let last_activity = Arc::new(RwLock::new(Instant::now()));
let worker_is_active = is_active.clone();
let worker_last_activity = last_activity.clone();
let worker_stats = stats.clone();
let handle = tokio::spawn(async move {
loop {
// 等待任务消息
let message = {
let mut receiver = task_receiver.lock().await;
receiver.recv().await
};
match message {
Some(WorkerMessage::NewTask) => {
worker_is_active.store(1, Ordering::Relaxed);
*worker_last_activity.write().await = Instant::now();
// 处理任务的逻辑在这里
// 实际实现中会从队列中获取任务并执行
worker_stats.record_task_completed().await;
worker_is_active.store(0, Ordering::Relaxed);
}
Some(WorkerMessage::Shutdown) => break,
None => break, // 通道关闭
}
}
});
Ok(Self {
id,
handle,
is_active,
last_activity,
})
}
pub async fn is_healthy(&self) -> bool {
let last_activity = *self.last_activity.read().await;
let inactive_duration = last_activity.elapsed();
// 如果工作线程超过5分钟没有活动认为不健康
inactive_duration < Duration::from_secs(300)
}
pub async fn restart(&self) -> Result<(), AppError> {
// 重启工作线程的逻辑
// 在实际实现中,这里会重新创建工作线程
Ok(())
}
}
/// 负载均衡器
pub struct LoadBalancer {
strategy: LoadBalancingStrategy,
stats: Arc<LoadBalancerStats>,
}
impl Default for LoadBalancer {
fn default() -> Self {
Self::new()
}
}
impl LoadBalancer {
pub fn new() -> Self {
Self {
strategy: LoadBalancingStrategy::RoundRobin,
stats: Arc::new(LoadBalancerStats::new()),
}
}
pub async fn balance(&self, _worker_pool: &WorkerPool) -> Result<(), AppError> {
match self.strategy {
LoadBalancingStrategy::RoundRobin => {
// 轮询负载均衡逻辑
}
LoadBalancingStrategy::LeastConnections => {
// 最少连接负载均衡逻辑
}
LoadBalancingStrategy::WeightedRoundRobin => {
// 加权轮询负载均衡逻辑
}
}
self.stats.record_balance_operation().await;
Ok(())
}
}
/// 任务句柄
pub struct TaskHandle<T> {
pub id: String,
result_rx: oneshot::Receiver<Result<T, AppError>>,
_permit: tokio::sync::OwnedSemaphorePermit,
}
impl<T> TaskHandle<T> {
/// 等待任务完成
pub async fn await_result(self) -> Result<T, AppError> {
match self.result_rx.await {
Ok(result) => result,
Err(_) => Err(AppError::Config("Task was cancelled".to_string())),
}
}
/// 等待任务完成(带超时)
pub async fn await_result_timeout(self, timeout: Duration) -> Result<T, AppError> {
match tokio::time::timeout(timeout, self.result_rx).await {
Ok(Ok(result)) => result,
Ok(Err(_)) => Err(AppError::Config("Task was cancelled".to_string())),
Err(_) => Err(AppError::Config("Task timed out".to_string())),
}
}
}
/// 并发任务
struct ConcurrentTask {
id: String,
task: Box<dyn FnOnce() -> BoxFuture<'static, ()> + Send>,
priority: TaskPriority,
submitted_at: Instant,
timeout: Duration,
}
/// 任务优先级
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
enum TaskPriority {
Low = 0,
Normal = 1,
High = 2,
Critical = 3,
}
/// 工作线程消息
enum WorkerMessage {
NewTask,
Shutdown,
}
/// 负载均衡策略
#[derive(Debug, Clone, Copy)]
enum LoadBalancingStrategy {
RoundRobin,
LeastConnections,
WeightedRoundRobin,
}
/// 并发统计
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ConcurrencyStats {
pub total_tasks_submitted: u64,
pub total_tasks_completed: u64,
pub total_tasks_failed: u64,
pub priority_tasks_submitted: u64,
pub average_task_duration: Duration,
pub peak_concurrent_tasks: usize,
pub queue_stats: QueueStatsData,
pub worker_stats: WorkerStatsData,
}
impl Default for ConcurrencyStats {
fn default() -> Self {
Self::new()
}
}
impl ConcurrencyStats {
pub fn new() -> Self {
Self {
total_tasks_submitted: 0,
total_tasks_completed: 0,
total_tasks_failed: 0,
priority_tasks_submitted: 0,
average_task_duration: Duration::from_secs(0),
peak_concurrent_tasks: 0,
queue_stats: QueueStatsData::new(),
worker_stats: WorkerStatsData::new(),
}
}
pub async fn record_task_submitted(&self) {
// 原子操作记录
}
pub async fn record_priority_task_submitted(&self) {
// 原子操作记录
}
pub async fn record_concurrency_adjustment(&self, _new_max: usize) {
// 记录并发调整
}
pub async fn clone_stats(&self) -> ConcurrencyStats {
self.clone()
}
pub async fn reset(&self) {
// 重置统计数据
}
}
/// 队列状态
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct QueueStatus {
pub pending_tasks: usize,
pub active_tasks: usize,
pub available_workers: usize,
pub queue_capacity: usize,
}
/// 其他统计结构
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct QueueStatsData {
pub enqueues: u64,
pub dequeues: u64,
pub priority_enqueues: u64,
pub priority_dequeues: u64,
pub cleanups: u64,
}
impl Default for QueueStatsData {
fn default() -> Self {
Self::new()
}
}
impl QueueStatsData {
pub fn new() -> Self {
Self {
enqueues: 0,
dequeues: 0,
priority_enqueues: 0,
priority_dequeues: 0,
cleanups: 0,
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct WorkerStatsData {
pub tasks_completed: u64,
pub tasks_failed: u64,
pub total_processing_time: Duration,
pub restarts: u64,
}
impl Default for WorkerStatsData {
fn default() -> Self {
Self::new()
}
}
impl WorkerStatsData {
pub fn new() -> Self {
Self {
tasks_completed: 0,
tasks_failed: 0,
total_processing_time: Duration::from_secs(0),
restarts: 0,
}
}
}
// 辅助统计结构
struct QueueStats {
enqueues: AtomicU64,
dequeues: AtomicU64,
priority_enqueues: AtomicU64,
priority_dequeues: AtomicU64,
cleanups: AtomicU64,
}
impl QueueStats {
fn new() -> Self {
Self {
enqueues: AtomicU64::new(0),
dequeues: AtomicU64::new(0),
priority_enqueues: AtomicU64::new(0),
priority_dequeues: AtomicU64::new(0),
cleanups: AtomicU64::new(0),
}
}
async fn record_enqueue(&self) {
self.enqueues.fetch_add(1, Ordering::Relaxed);
}
async fn record_dequeue(&self) {
self.dequeues.fetch_add(1, Ordering::Relaxed);
}
async fn record_priority_enqueue(&self) {
self.priority_enqueues.fetch_add(1, Ordering::Relaxed);
}
async fn record_priority_dequeue(&self) {
self.priority_dequeues.fetch_add(1, Ordering::Relaxed);
}
async fn record_cleanup(&self) {
self.cleanups.fetch_add(1, Ordering::Relaxed);
}
}
struct WorkerStats {
active_workers: AtomicUsize,
tasks_completed: AtomicU64,
tasks_failed: AtomicU64,
}
impl WorkerStats {
fn new() -> Self {
Self {
active_workers: AtomicUsize::new(0),
tasks_completed: AtomicU64::new(0),
tasks_failed: AtomicU64::new(0),
}
}
async fn active_workers(&self) -> usize {
self.active_workers.load(Ordering::Relaxed)
}
async fn record_task_completed(&self) {
self.tasks_completed.fetch_add(1, Ordering::Relaxed);
}
}
struct LoadBalancerStats {
balance_operations: AtomicU64,
}
impl LoadBalancerStats {
fn new() -> Self {
Self {
balance_operations: AtomicU64::new(0),
}
}
async fn record_balance_operation(&self) {
self.balance_operations.fetch_add(1, Ordering::Relaxed);
}
}

View File

@@ -0,0 +1,707 @@
//! 内存优化器
//!
//! 提供内存使用监控、内存池管理和内存压缩功能
use dashmap::DashMap;
use flate2::Compression;
use flate2::read::GzDecoder;
use flate2::write::GzEncoder;
use std::collections::VecDeque;
use std::io::{Read, Write};
use std::sync::Arc;
use std::sync::atomic::{AtomicU64, AtomicUsize, Ordering};
use std::time::{Duration, Instant};
use tokio::sync::{Mutex, RwLock};
use tokio_util::bytes::BytesMut;
use super::{MemoryConfig, PerformanceOptimizable};
use crate::config::AppConfig;
use crate::error::AppError;
/// 内存优化器
pub struct MemoryOptimizer {
config: MemoryConfig,
memory_pool: Arc<MemoryPool>,
compression_manager: Arc<CompressionManager>,
memory_monitor: Arc<MemoryMonitor>,
stats: Arc<MemoryStats>,
}
impl MemoryOptimizer {
/// 创建新的内存优化器
pub async fn new(_config: &AppConfig) -> Result<Self, AppError> {
let memory_config = MemoryConfig::default(); // 从配置中获取
let memory_pool = Arc::new(MemoryPool::new(memory_config.pool_size));
let compression_manager =
Arc::new(CompressionManager::new(memory_config.enable_compression));
let memory_monitor = Arc::new(MemoryMonitor::new(memory_config.max_memory_usage));
let stats = Arc::new(MemoryStats::new());
Ok(Self {
config: memory_config,
memory_pool,
compression_manager,
memory_monitor,
stats,
})
}
/// 分配内存
pub async fn allocate(&self, size: usize) -> Result<MemoryBlock, AppError> {
// 检查内存限制
if !self.memory_monitor.can_allocate(size).await {
// 尝试清理内存
self.cleanup_memory().await?;
// 再次检查
if !self.memory_monitor.can_allocate(size).await {
return Err(AppError::Config(format!(
"Memory limit exceeded: requested {} bytes, available {} bytes",
size,
self.memory_monitor.available_memory().await
)));
}
}
// 从内存池分配
let block = self.memory_pool.allocate(size).await?;
// 更新统计
self.stats.record_allocation(size);
self.memory_monitor.record_allocation(size).await;
Ok(block)
}
/// 释放内存
pub async fn deallocate(&self, block: MemoryBlock) -> Result<(), AppError> {
let size = block.size();
// 返回到内存池
self.memory_pool.deallocate(block).await?;
// 更新统计
self.stats.record_deallocation(size);
self.memory_monitor.record_deallocation(size).await;
Ok(())
}
/// 压缩数据
pub async fn compress(&self, data: &[u8]) -> Result<Vec<u8>, AppError> {
if !self.config.enable_compression {
return Ok(data.to_vec());
}
self.compression_manager.compress(data).await
}
/// 解压数据
pub async fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, AppError> {
if !self.config.enable_compression {
return Ok(data.to_vec());
}
self.compression_manager.decompress(data).await
}
/// 清理内存
pub async fn cleanup_memory(&self) -> Result<(), AppError> {
// 清理内存池
self.memory_pool.cleanup().await?;
// 强制垃圾回收(如果可能)
#[cfg(target_os = "linux")]
{
// 在 Linux 上尝试将空闲内存归还给系统
unsafe {
libc::malloc_trim(0);
}
}
self.stats.record_cleanup();
Ok(())
}
/// 获取内存统计
pub async fn get_memory_stats(&self) -> Result<MemoryStats, AppError> {
Ok(self.stats.clone_stats().await)
}
/// 获取内存使用情况
pub async fn get_memory_usage(&self) -> Result<MemoryUsage, AppError> {
Ok(MemoryUsage {
total_allocated: self.memory_monitor.total_allocated().await,
total_available: self.memory_monitor.available_memory().await,
pool_usage: self.memory_pool.usage().await,
compression_ratio: self.compression_manager.compression_ratio().await,
})
}
}
#[async_trait::async_trait]
impl PerformanceOptimizable for MemoryOptimizer {
async fn optimize(&self) -> Result<(), AppError> {
// 检查内存使用情况
let usage = self.get_memory_usage().await?;
let usage_ratio = usage.total_allocated as f64 / usage.total_available as f64;
// 如果内存使用超过阈值,执行清理
if usage_ratio > self.config.cleanup_threshold {
self.cleanup_memory().await?;
}
// 优化内存池
self.memory_pool.optimize().await?;
Ok(())
}
async fn get_stats(&self) -> Result<serde_json::Value, AppError> {
let stats = self.get_memory_stats().await?;
let usage = self.get_memory_usage().await?;
Ok(serde_json::json!({
"stats": stats,
"usage": usage
}))
}
async fn reset_stats(&self) -> Result<(), AppError> {
self.stats.reset().await;
Ok(())
}
}
/// 内存池
pub struct MemoryPool {
pools: DashMap<usize, Arc<Mutex<VecDeque<MemoryBlock>>>>,
max_pool_size: usize,
stats: Arc<PoolStats>,
}
impl MemoryPool {
pub fn new(max_pool_size: usize) -> Self {
Self {
pools: DashMap::new(),
max_pool_size,
stats: Arc::new(PoolStats::new()),
}
}
pub async fn allocate(&self, size: usize) -> Result<MemoryBlock, AppError> {
// 计算合适的块大小2的幂次
let block_size = self.calculate_block_size(size);
// 尝试从池中获取
if let Some(pool) = self.pools.get(&block_size) {
let mut pool_guard = pool.lock().await;
if let Some(block) = pool_guard.pop_front() {
self.stats.record_pool_hit();
return Ok(block);
}
}
// 池中没有可用块,创建新块
let block = MemoryBlock::new(block_size)?;
self.stats.record_pool_miss();
Ok(block)
}
pub async fn deallocate(&self, block: MemoryBlock) -> Result<(), AppError> {
let block_size = block.size();
// 获取或创建对应大小的池
let pool = self
.pools
.entry(block_size)
.or_insert_with(|| Arc::new(Mutex::new(VecDeque::new())))
.clone();
let mut pool_guard = pool.lock().await;
// 如果池未满,将块返回到池中
if pool_guard.len() < self.max_pool_size {
pool_guard.push_back(block);
self.stats.record_pool_return();
} else {
// 池已满,直接丢弃块
drop(block);
self.stats.record_pool_discard();
}
Ok(())
}
pub async fn cleanup(&self) -> Result<(), AppError> {
// 清理所有池中的一半块
for entry in self.pools.iter() {
let pool = entry.value().clone();
let mut pool_guard = pool.lock().await;
let current_size = pool_guard.len();
let target_size = current_size / 2;
while pool_guard.len() > target_size {
pool_guard.pop_back();
}
}
self.stats.record_cleanup();
Ok(())
}
pub async fn optimize(&self) -> Result<(), AppError> {
// 移除空的池
self.pools.retain(|_, pool| {
if let Ok(guard) = pool.try_lock() {
!guard.is_empty()
} else {
true // 如果无法获取锁,保留池
}
});
Ok(())
}
pub async fn usage(&self) -> PoolUsage {
let mut total_blocks = 0;
let mut total_memory = 0;
for entry in self.pools.iter() {
let block_size = *entry.key();
if let Ok(pool_guard) = entry.value().try_lock() {
let count = pool_guard.len();
total_blocks += count;
total_memory += count * block_size;
}
}
PoolUsage {
total_pools: self.pools.len(),
total_blocks,
total_memory,
stats: self.stats.get_stats().await,
}
}
fn calculate_block_size(&self, size: usize) -> usize {
// 向上舍入到最近的2的幂次
let mut block_size = 1;
while block_size < size {
block_size <<= 1;
}
block_size.max(64) // 最小64字节
}
}
/// 内存块
pub struct MemoryBlock {
data: BytesMut,
size: usize,
allocated_at: Instant,
}
impl MemoryBlock {
pub fn new(size: usize) -> Result<Self, AppError> {
let data = BytesMut::with_capacity(size);
Ok(Self {
data,
size,
allocated_at: Instant::now(),
})
}
pub fn size(&self) -> usize {
self.size
}
pub fn data(&self) -> &[u8] {
&self.data
}
pub fn data_mut(&mut self) -> &mut BytesMut {
&mut self.data
}
pub fn age(&self) -> Duration {
self.allocated_at.elapsed()
}
}
/// 压缩管理器
pub struct CompressionManager {
enabled: bool,
compression_level: Compression,
stats: Arc<CompressionStats>,
}
impl CompressionManager {
pub fn new(enabled: bool) -> Self {
Self {
enabled,
compression_level: Compression::default(),
stats: Arc::new(CompressionStats::new()),
}
}
pub async fn compress(&self, data: &[u8]) -> Result<Vec<u8>, AppError> {
if !self.enabled {
return Ok(data.to_vec());
}
let start = Instant::now();
let original_size = data.len();
let mut encoder = GzEncoder::new(Vec::new(), self.compression_level);
encoder.write_all(data)?;
let compressed = encoder
.finish()
.map_err(|e| AppError::Config(format!("Compression error: {e}")))?;
let compressed_size = compressed.len();
let duration = start.elapsed();
self.stats
.record_compression(original_size, compressed_size, duration)
.await;
Ok(compressed)
}
pub async fn decompress(&self, data: &[u8]) -> Result<Vec<u8>, AppError> {
if !self.enabled {
return Ok(data.to_vec());
}
let start = Instant::now();
let compressed_size = data.len();
let mut decoder = GzDecoder::new(data);
let mut decompressed = Vec::new();
decoder.read_to_end(&mut decompressed)?;
let decompressed_size = decompressed.len();
let duration = start.elapsed();
self.stats
.record_decompression(compressed_size, decompressed_size, duration)
.await;
Ok(decompressed)
}
pub async fn compression_ratio(&self) -> f64 {
self.stats.average_compression_ratio().await
}
}
/// 内存监控器
pub struct MemoryMonitor {
max_memory: u64,
current_allocated: AtomicU64,
peak_allocated: AtomicU64,
allocation_count: AtomicUsize,
deallocation_count: AtomicUsize,
}
impl MemoryMonitor {
pub fn new(max_memory: u64) -> Self {
Self {
max_memory,
current_allocated: AtomicU64::new(0),
peak_allocated: AtomicU64::new(0),
allocation_count: AtomicUsize::new(0),
deallocation_count: AtomicUsize::new(0),
}
}
pub async fn can_allocate(&self, size: usize) -> bool {
let current = self.current_allocated.load(Ordering::Relaxed);
current + size as u64 <= self.max_memory
}
pub async fn record_allocation(&self, size: usize) {
let new_allocated = self
.current_allocated
.fetch_add(size as u64, Ordering::Relaxed)
+ size as u64;
// 更新峰值
let mut peak = self.peak_allocated.load(Ordering::Relaxed);
while new_allocated > peak {
match self.peak_allocated.compare_exchange_weak(
peak,
new_allocated,
Ordering::Relaxed,
Ordering::Relaxed,
) {
Ok(_) => break,
Err(current_peak) => peak = current_peak,
}
}
self.allocation_count.fetch_add(1, Ordering::Relaxed);
}
pub async fn record_deallocation(&self, size: usize) {
self.current_allocated
.fetch_sub(size as u64, Ordering::Relaxed);
self.deallocation_count.fetch_add(1, Ordering::Relaxed);
}
pub async fn total_allocated(&self) -> u64 {
self.current_allocated.load(Ordering::Relaxed)
}
pub async fn available_memory(&self) -> u64 {
let current = self.current_allocated.load(Ordering::Relaxed);
self.max_memory.saturating_sub(current)
}
pub async fn peak_memory(&self) -> u64 {
self.peak_allocated.load(Ordering::Relaxed)
}
}
/// 内存统计
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MemoryStats {
pub total_allocations: u64,
pub total_deallocations: u64,
pub current_allocated: u64,
pub peak_allocated: u64,
pub cleanup_count: u64,
pub compression_stats: CompressionStatsData,
pub pool_stats: PoolStatsData,
}
impl Default for MemoryStats {
fn default() -> Self {
Self::new()
}
}
impl MemoryStats {
pub fn new() -> Self {
Self {
total_allocations: 0,
total_deallocations: 0,
current_allocated: 0,
peak_allocated: 0,
cleanup_count: 0,
compression_stats: CompressionStatsData::new(),
pool_stats: PoolStatsData::new(),
}
}
pub fn record_allocation(&self, _size: usize) {
// 在实际实现中,这些应该是原子操作
}
pub fn record_deallocation(&self, _size: usize) {
// 在实际实现中,这些应该是原子操作
}
pub fn record_cleanup(&self) {
// 在实际实现中,这些应该是原子操作
}
pub async fn clone_stats(&self) -> MemoryStats {
self.clone()
}
pub async fn reset(&self) {
// 重置统计数据
}
}
/// 其他统计结构
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MemoryUsage {
pub total_allocated: u64,
pub total_available: u64,
pub pool_usage: PoolUsage,
pub compression_ratio: f64,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PoolUsage {
pub total_pools: usize,
pub total_blocks: usize,
pub total_memory: usize,
pub stats: PoolStatsData,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PoolStatsData {
pub hits: u64,
pub misses: u64,
pub returns: u64,
pub discards: u64,
pub cleanups: u64,
}
impl Default for PoolStatsData {
fn default() -> Self {
Self::new()
}
}
impl PoolStatsData {
pub fn new() -> Self {
Self {
hits: 0,
misses: 0,
returns: 0,
discards: 0,
cleanups: 0,
}
}
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CompressionStatsData {
pub compressions: u64,
pub decompressions: u64,
pub total_original_size: u64,
pub total_compressed_size: u64,
pub average_compression_time: Duration,
pub average_decompression_time: Duration,
}
impl Default for CompressionStatsData {
fn default() -> Self {
Self::new()
}
}
impl CompressionStatsData {
pub fn new() -> Self {
Self {
compressions: 0,
decompressions: 0,
total_original_size: 0,
total_compressed_size: 0,
average_compression_time: Duration::from_secs(0),
average_decompression_time: Duration::from_secs(0),
}
}
}
// 辅助结构的实现
struct PoolStats {
hits: AtomicU64,
misses: AtomicU64,
returns: AtomicU64,
discards: AtomicU64,
cleanups: AtomicU64,
}
impl PoolStats {
fn new() -> Self {
Self {
hits: AtomicU64::new(0),
misses: AtomicU64::new(0),
returns: AtomicU64::new(0),
discards: AtomicU64::new(0),
cleanups: AtomicU64::new(0),
}
}
fn record_pool_hit(&self) {
self.hits.fetch_add(1, Ordering::Relaxed);
}
fn record_pool_miss(&self) {
self.misses.fetch_add(1, Ordering::Relaxed);
}
fn record_pool_return(&self) {
self.returns.fetch_add(1, Ordering::Relaxed);
}
fn record_pool_discard(&self) {
self.discards.fetch_add(1, Ordering::Relaxed);
}
fn record_cleanup(&self) {
self.cleanups.fetch_add(1, Ordering::Relaxed);
}
async fn get_stats(&self) -> PoolStatsData {
PoolStatsData {
hits: self.hits.load(Ordering::Relaxed),
misses: self.misses.load(Ordering::Relaxed),
returns: self.returns.load(Ordering::Relaxed),
discards: self.discards.load(Ordering::Relaxed),
cleanups: self.cleanups.load(Ordering::Relaxed),
}
}
}
struct CompressionStats {
compressions: AtomicU64,
decompressions: AtomicU64,
total_original_size: AtomicU64,
total_compressed_size: AtomicU64,
total_compression_time: RwLock<Duration>,
total_decompression_time: RwLock<Duration>,
}
impl CompressionStats {
fn new() -> Self {
Self {
compressions: AtomicU64::new(0),
decompressions: AtomicU64::new(0),
total_original_size: AtomicU64::new(0),
total_compressed_size: AtomicU64::new(0),
total_compression_time: RwLock::new(Duration::from_secs(0)),
total_decompression_time: RwLock::new(Duration::from_secs(0)),
}
}
async fn record_compression(
&self,
original_size: usize,
compressed_size: usize,
duration: Duration,
) {
self.compressions.fetch_add(1, Ordering::Relaxed);
self.total_original_size
.fetch_add(original_size as u64, Ordering::Relaxed);
self.total_compressed_size
.fetch_add(compressed_size as u64, Ordering::Relaxed);
let mut total_time = self.total_compression_time.write().await;
*total_time += duration;
}
async fn record_decompression(
&self,
_compressed_size: usize,
_decompressed_size: usize,
duration: Duration,
) {
self.decompressions.fetch_add(1, Ordering::Relaxed);
let mut total_time = self.total_decompression_time.write().await;
*total_time += duration;
}
async fn average_compression_ratio(&self) -> f64 {
let original = self.total_original_size.load(Ordering::Relaxed);
let compressed = self.total_compressed_size.load(Ordering::Relaxed);
if original > 0 {
compressed as f64 / original as f64
} else {
1.0
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,439 @@
//! 性能优化模块
//!
//! 包含内存使用优化、并发处理优化和缓存策略
pub mod cache_manager;
pub mod concurrency_optimizer;
pub mod memory_optimizer;
pub mod metrics_collector;
// pub mod resource_monitor; // 模块不存在,暂时注释
use crate::config::AppConfig;
use crate::error::AppError;
use serde::{Deserialize, Serialize};
use std::sync::Arc;
use std::time::{Duration, SystemTime};
/// 性能优化器主结构
#[derive(Clone)]
pub struct PerformanceOptimizer {
memory_optimizer: Arc<memory_optimizer::MemoryOptimizer>,
concurrency_optimizer: Arc<concurrency_optimizer::ConcurrencyOptimizer>,
cache_manager: Arc<cache_manager::CacheManager>,
metrics_collector: Arc<metrics_collector::MetricsCollector>,
// resource_monitor: Arc<resource_monitor::ResourceMonitor>, // 模块不存在,暂时注释
_config: PerformanceConfig,
}
impl PerformanceOptimizer {
/// 创建新的性能优化器
pub async fn new(config: &AppConfig) -> Result<Self, AppError> {
let performance_config = PerformanceConfig::default();
let memory_optimizer = Arc::new(memory_optimizer::MemoryOptimizer::new(config).await?);
let concurrency_optimizer =
Arc::new(concurrency_optimizer::ConcurrencyOptimizer::new(config).await?);
let cache_manager = Arc::new(cache_manager::CacheManager::new(config).await?);
let metrics_collector = Arc::new(metrics_collector::MetricsCollector::new(config).await?);
// let resource_monitor = Arc::new(resource_monitor::ResourceMonitor::new(config).await?); // 模块不存在,暂时注释
Ok(Self {
memory_optimizer,
concurrency_optimizer,
cache_manager,
metrics_collector,
// resource_monitor, // 模块不存在,暂时注释
_config: performance_config,
})
}
/// 启动性能监控
pub async fn start_monitoring(&self) -> Result<(), AppError> {
// self.resource_monitor.start_monitoring().await?; // 模块不存在,暂时注释
// self.metrics_collector.start_monitoring().await?; // 方法不存在,暂时注释
Ok(())
}
/// 停止性能监控
pub async fn stop_monitoring(&self) -> Result<(), AppError> {
// self.resource_monitor.stop_monitoring().await?; // 模块不存在,暂时注释
// self.metrics_collector.stop_monitoring().await?; // 方法不存在,暂时注释
Ok(())
}
/// 获取内存优化器
pub fn memory_optimizer(&self) -> &Arc<memory_optimizer::MemoryOptimizer> {
&self.memory_optimizer
}
/// 获取并发优化器
pub fn concurrency_optimizer(&self) -> &Arc<concurrency_optimizer::ConcurrencyOptimizer> {
&self.concurrency_optimizer
}
/// 获取缓存管理器
pub fn cache_manager(&self) -> &Arc<cache_manager::CacheManager> {
&self.cache_manager
}
/// 获取指标收集器
pub fn metrics_collector(&self) -> &Arc<metrics_collector::MetricsCollector> {
&self.metrics_collector
}
// /// 获取资源监控器
// pub fn resource_monitor(&self) -> &Arc<resource_monitor::ResourceMonitor> {
// &self.resource_monitor
// } // 模块不存在,暂时注释
// /// 启动资源监控
// pub async fn start_resource_monitoring(&self) -> Result<(), DocumentParserError> {
// self.resource_monitor.start_monitoring().await
// } // 模块不存在,暂时注释
// /// 停止资源监控
// pub async fn stop_resource_monitoring(&self) -> Result<(), DocumentParserError> {
// self.resource_monitor.stop_monitoring().await
// } // 模块不存在,暂时注释
// /// 获取资源统计
// pub async fn get_resource_stats(&self) -> Result<resource_monitor::ResourceStats, DocumentParserError> {
// self.resource_monitor.get_stats().await
// } // 模块不存在,暂时注释
/// 优化资源使用
pub async fn optimize_resources(&self) -> Result<(), AppError> {
// self.resource_monitor.optimize().await // 模块不存在,暂时注释
Ok(())
}
/// 执行性能优化
pub async fn optimize(&self) -> Result<(), AppError> {
// 执行内存优化
self.memory_optimizer.optimize().await?;
// 执行并发优化
self.concurrency_optimizer.optimize().await?;
// 执行缓存优化
self.cache_manager.optimize().await?;
Ok(())
}
/// 获取性能报告
pub async fn get_performance_report(&self) -> Result<PerformanceReport, AppError> {
// let system_resources = self.resource_monitor.get_system_resources().await?; // 模块不存在,暂时注释
// let app_resources = self.resource_monitor.get_application_resources().await?; // 模块不存在,暂时注释
let metrics = self.metrics_collector.get_stats().await?;
let cache_stats = self.cache_manager.get_stats().await?;
Ok(PerformanceReport {
system_resources: Default::default(),
application_resources: Default::default(),
metrics,
cache_stats,
generated_at: SystemTime::now(),
})
}
}
/// 性能报告
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PerformanceReport {
pub system_resources: serde_json::Value, // resource_monitor::SystemResourceStatus, // 模块不存在,暂时使用通用类型
pub application_resources: serde_json::Value, // resource_monitor::ApplicationResourceStatus, // 模块不存在,暂时使用通用类型
pub metrics: serde_json::Value,
pub cache_stats: serde_json::Value,
pub generated_at: SystemTime,
}
/// 详细性能报告
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct DetailedPerformanceReport {
pub memory_stats: memory_optimizer::MemoryStats,
pub concurrency_stats: concurrency_optimizer::ConcurrencyStats,
pub cache_stats: cache_manager::CacheStats,
pub metrics: metrics_collector::MetricsSnapshot,
// pub resource_stats: resource_monitor::ResourceStats, // 模块不存在,暂时注释
pub timestamp: chrono::DateTime<chrono::Utc>,
}
/// 性能配置
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct PerformanceConfig {
/// 内存优化配置
pub memory: MemoryConfig,
/// 并发优化配置
pub concurrency: ConcurrencyConfig,
/// 缓存配置
pub cache: CacheConfig,
/// 资源配置
pub resource: ResourceConfig,
/// 监控配置
pub monitoring: MonitoringConfig,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ResourceConfig {
pub max_cpu_usage: f64,
pub max_memory_usage: u64,
pub max_disk_usage: u64,
pub max_network_bandwidth: u64,
pub max_connections: usize,
pub max_file_descriptors: usize,
pub min_instances: usize,
pub max_instances: usize,
pub monitoring_interval: Duration,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MemoryConfig {
/// 最大内存使用量(字节)
pub max_memory_usage: u64,
/// 内存清理阈值(百分比)
pub cleanup_threshold: f64,
/// 内存池大小
pub pool_size: usize,
/// 启用内存压缩
pub enable_compression: bool,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct ConcurrencyConfig {
/// 最大并发任务数
pub max_concurrent_tasks: usize,
/// 任务队列大小
pub task_queue_size: usize,
/// 工作线程数
pub worker_threads: usize,
/// 任务超时时间
pub task_timeout: Duration,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct CacheConfig {
/// 缓存大小(字节)
pub cache_size: u64,
/// 文档缓存大小
pub document_cache_size: usize,
/// 结果缓存大小
pub result_cache_size: usize,
/// 元数据缓存大小
pub metadata_cache_size: usize,
/// 缓存TTL
pub ttl: Duration,
/// 文档缓存TTL
pub document_ttl: Duration,
/// 结果缓存TTL
pub result_ttl: Duration,
/// 元数据缓存TTL
pub metadata_ttl: Duration,
/// 清理间隔
pub cleanup_interval: Duration,
/// 启用LRU淘汰
pub enable_lru: bool,
/// 缓存压缩
pub enable_compression: bool,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MonitoringConfig {
/// 监控间隔
pub interval: Duration,
/// 启用详细监控
pub enable_detailed: bool,
/// 保留历史数据时间
pub retention_period: Duration,
}
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
pub struct MetricsConfig {
/// 指标收集间隔
pub collection_interval: Duration,
/// 启用系统指标收集
pub enable_system_metrics: bool,
/// 启用应用指标收集
pub enable_application_metrics: bool,
/// 启用自定义指标
pub enable_custom_metrics: bool,
/// 指标保留时间
pub retention_period: Duration,
/// 聚合窗口大小
pub aggregation_window: Duration,
/// 聚合间隔
pub aggregation_interval: Duration,
/// 启用指标导出
pub enable_export: bool,
/// 导出格式
pub export_format: String,
/// 报告生成间隔
pub report_interval: Duration,
/// 报告间隔
pub reporting_interval: Duration,
}
impl Default for PerformanceConfig {
fn default() -> Self {
Self {
memory: MemoryConfig {
max_memory_usage: 2 * 1024 * 1024 * 1024, // 2GB
cleanup_threshold: 0.8, // 80%
pool_size: 100,
enable_compression: true,
},
concurrency: ConcurrencyConfig {
max_concurrent_tasks: 10,
task_queue_size: 100,
worker_threads: num_cpus::get(),
task_timeout: Duration::from_secs(1800), // 30分钟
},
cache: CacheConfig {
cache_size: 512 * 1024 * 1024, // 512MB
document_cache_size: 1000,
result_cache_size: 500,
metadata_cache_size: 200,
ttl: Duration::from_secs(3600), // 1小时
document_ttl: Duration::from_secs(3600), // 1小时
result_ttl: Duration::from_secs(1800), // 30分钟
metadata_ttl: Duration::from_secs(7200), // 2小时
cleanup_interval: Duration::from_secs(300), // 5分钟
enable_lru: true,
enable_compression: true,
},
resource: ResourceConfig {
max_cpu_usage: 80.0,
max_memory_usage: 8 * 1024 * 1024 * 1024, // 8GB
max_disk_usage: 100 * 1024 * 1024 * 1024, // 100GB
max_network_bandwidth: 1024 * 1024 * 1024, // 1GB/s
max_connections: 1000,
max_file_descriptors: 10000,
min_instances: 1,
max_instances: 10,
monitoring_interval: Duration::from_secs(30),
},
monitoring: MonitoringConfig {
interval: Duration::from_secs(30),
enable_detailed: false,
retention_period: Duration::from_secs(24 * 3600), // 24小时
},
}
}
}
impl Default for MemoryConfig {
fn default() -> Self {
Self {
max_memory_usage: 1024 * 1024 * 1024, // 1GB
cleanup_threshold: 0.8,
pool_size: 100,
enable_compression: true,
}
}
}
impl Default for ConcurrencyConfig {
fn default() -> Self {
Self {
max_concurrent_tasks: 10,
task_queue_size: 1000,
worker_threads: 4,
task_timeout: Duration::from_secs(300),
}
}
}
impl Default for CacheConfig {
fn default() -> Self {
Self {
cache_size: 100 * 1024 * 1024, // 100MB
document_cache_size: 1000,
result_cache_size: 500,
metadata_cache_size: 2000,
ttl: Duration::from_secs(3600), // 1 hour
document_ttl: Duration::from_secs(3600), // 1 hour
result_ttl: Duration::from_secs(1800), // 30 minutes
metadata_ttl: Duration::from_secs(7200), // 2 hours
cleanup_interval: Duration::from_secs(300), // 5 minutes
enable_lru: true,
enable_compression: false,
}
}
}
impl Default for MonitoringConfig {
fn default() -> Self {
Self {
interval: Duration::from_secs(30),
enable_detailed: false,
retention_period: Duration::from_secs(86400), // 24 hours
}
}
}
impl Default for ResourceConfig {
fn default() -> Self {
Self {
max_cpu_usage: 80.0,
max_memory_usage: 1024 * 1024 * 1024, // 1GB
max_disk_usage: 10 * 1024 * 1024 * 1024, // 10GB
max_network_bandwidth: 100 * 1024 * 1024, // 100MB/s
max_connections: 1000,
max_file_descriptors: 1024,
min_instances: 1,
max_instances: 10,
monitoring_interval: Duration::from_secs(60),
}
}
}
impl Default for MetricsConfig {
fn default() -> Self {
Self {
collection_interval: Duration::from_secs(30),
enable_system_metrics: true,
enable_application_metrics: true,
enable_custom_metrics: false,
retention_period: Duration::from_secs(3600 * 24), // 24小时
aggregation_window: Duration::from_secs(300), // 5分钟
aggregation_interval: Duration::from_secs(60), // 1分钟
enable_export: false,
export_format: "json".to_string(),
report_interval: Duration::from_secs(300), // 5分钟
reporting_interval: Duration::from_secs(300), // 5分钟
}
}
}
/// 性能优化特征
#[async_trait::async_trait]
pub trait PerformanceOptimizable {
/// 执行性能优化
async fn optimize(&self) -> Result<(), AppError>;
/// 获取性能统计
async fn get_stats(&self) -> Result<serde_json::Value, AppError>;
/// 重置性能统计
async fn reset_stats(&self) -> Result<(), AppError>;
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_performance_optimizer_creation() {
// 使用默认配置进行测试
let config = crate::config::AppConfig::load_base_config().unwrap();
let optimizer = PerformanceOptimizer::new(&config).await;
assert!(optimizer.is_ok());
}
#[tokio::test]
async fn test_performance_config_default() {
let config = PerformanceConfig::default();
assert!(config.memory.max_memory_usage > 0);
assert!(config.concurrency.max_concurrent_tasks > 0);
assert!(config.cache.cache_size > 0);
}
}

File diff suppressed because it is too large Load Diff