Coverage for src\performance.py: 0%
140 statements
« prev ^ index » next coverage.py v7.3.4, created at 2026-04-21 14:54 +0800
« prev ^ index » next coverage.py v7.3.4, created at 2026-04-21 14:54 +0800
1"""
2PAO系统性能优化模块
4提供:
5- 数据库查询优化
6- 网络通信压缩
7- 内存使用优化
8- 缓存管理
9"""
11import time
12import asyncio
13import psutil
14import logging
15from typing import Dict, Any, Optional, Callable
16from dataclasses import dataclass
17from functools import wraps
18import hashlib
19import json
21logger = logging.getLogger(__name__)
24@dataclass
25class PerformanceMetrics:
26 """性能指标"""
27 operation: str
28 duration_ms: float
29 memory_before_mb: float
30 memory_after_mb: float
31 timestamp: float
34class PerformanceMonitor:
35 """性能监控器"""
37 def __init__(self):
38 self.metrics: list[PerformanceMetrics] = []
39 self.process = psutil.Process()
41 def record(self, operation: str, duration_ms: float,
42 memory_before_mb: float, memory_after_mb: float):
43 """记录性能指标"""
44 metric = PerformanceMetrics(
45 operation=operation,
46 duration_ms=duration_ms,
47 memory_before_mb=memory_before_mb,
48 memory_after_mb=memory_after_mb,
49 timestamp=time.time()
50 )
51 self.metrics.append(metric)
53 def get_metrics(self, operation: Optional[str] = None) -> list[PerformanceMetrics]:
54 """获取性能指标"""
55 if operation:
56 return [m for m in self.metrics if m.operation == operation]
57 return self.metrics
59 def get_average_duration(self, operation: str) -> float:
60 """获取平均执行时间"""
61 metrics = self.get_metrics(operation)
62 if not metrics:
63 return 0.0
64 return sum(m.duration_ms for m in metrics) / len(metrics)
66 def clear(self):
67 """清空指标"""
68 self.metrics.clear()
71class CacheManager:
72 """缓存管理器"""
74 def __init__(self, max_size_mb: int = 100, ttl_seconds: int = 300):
75 self.max_size_mb = max_size_mb
76 self.ttl_seconds = ttl_seconds
77 self._cache: Dict[str, tuple[Any, float]] = {}
78 self._hits = 0
79 self._misses = 0
81 def get(self, key: str) -> Optional[Any]:
82 """获取缓存"""
83 if key in self._cache:
84 value, timestamp = self._cache[key]
85 if time.time() - timestamp < self.ttl_seconds:
86 self._hits += 1
87 return value
88 else:
89 del self._cache[key]
90 self._misses += 1
91 return None
93 def set(self, key: str, value: Any):
94 """设置缓存"""
95 self._cache[key] = (value, time.time())
97 def invalidate(self, key: str):
98 """使缓存失效"""
99 if key in self._cache:
100 del self._cache[key]
102 def clear(self):
103 """清空缓存"""
104 self._cache.clear()
105 self._hits = 0
106 self._misses = 0
108 def get_stats(self) -> Dict[str, Any]:
109 """获取缓存统计"""
110 total = self._hits + self._misses
111 hit_rate = self._hits / total if total > 0 else 0
112 return {
113 "size": len(self._cache),
114 "hits": self._hits,
115 "misses": self._misses,
116 "hit_rate": hit_rate
117 }
120def timed(metric_name: str = "operation"):
121 """性能计时装饰器"""
122 def decorator(func: Callable):
123 @wraps(func)
124 async def async_wrapper(*args, **kwargs):
125 start = time.perf_counter()
126 mem_before = psutil.Process().memory_info().rss / 1024 / 1024
127 try:
128 result = await func(*args, **kwargs)
129 return result
130 finally:
131 duration = (time.perf_counter() - start) * 1000
132 mem_after = psutil.Process().memory_info().rss / 1024 / 1024
133 logger.debug(f"{metric_name}: {duration:.2f}ms, mem: {mem_before:.1f}->{mem_after:.1f}MB")
134 @wraps(func)
135 def sync_wrapper(*args, **kwargs):
136 start = time.perf_counter()
137 mem_before = psutil.Process().memory_info().rss / 1024 / 1024
138 try:
139 result = func(*args, **kwargs)
140 return result
141 finally:
142 duration = (time.perf_counter() - start) * 1000
143 mem_after = psutil.Process().memory_info().rss / 1024 / 1024
144 logger.debug(f"{metric_name}: {duration:.2f}ms, mem: {mem_before:.1f}->{mem_after:.1f}MB")
145 if asyncio.iscoroutinefunction(func):
146 return async_wrapper
147 return sync_wrapper
148 return decorator
151class DataCompressor:
152 """数据压缩器"""
154 @staticmethod
155 def compress(data: str) -> bytes:
156 """压缩数据(使用简单编码)"""
157 if not data:
158 return b""
159 # 简单压缩:移除多余空白
160 compressed = " ".join(data.split())
161 return compressed.encode('utf-8')
163 @staticmethod
164 def decompress(data: bytes) -> str:
165 """解压数据"""
166 if not data:
167 return ""
168 return data.decode('utf-8')
170 @staticmethod
171 def should_compress(data: str, threshold: int = 1024) -> bool:
172 """判断是否应该压缩"""
173 return len(data) > threshold
176class QueryOptimizer:
177 """查询优化器"""
179 def __init__(self):
180 self._query_cache = CacheManager(max_size_mb=50, ttl_seconds=60)
182 def get_cached_query(self, query_key: str) -> Optional[Any]:
183 """获取缓存的查询结果"""
184 return self._query_cache.get(query_key)
186 def cache_query_result(self, query_key: str, result: Any):
187 """缓存查询结果"""
188 self._query_cache.set(query_key, result)
190 @staticmethod
191 def generate_query_key(query: str, params: Dict[str, Any]) -> str:
192 """生成查询缓存键"""
193 key_data = json.dumps({"query": query, "params": params}, sort_keys=True)
194 return hashlib.md5(key_data.encode()).hexdigest()
197class MemoryOptimizer:
198 """内存优化器"""
200 def __init__(self):
201 self.process = psutil.Process()
202 self._peak_memory_mb = 0
204 def get_current_memory_mb(self) -> float:
205 """获取当前内存使用(MB)"""
206 return self.process.memory_info().rss / 1024 / 1024
208 def get_memory_percent(self) -> float:
209 """获取内存使用百分比"""
210 return self.process.memory_percent()
212 def track_peak(self):
213 """追踪峰值内存"""
214 current = self.get_current_memory_mb()
215 if current > self._peak_memory_mb:
216 self._peak_memory_mb = current
218 def get_peak_memory_mb(self) -> float:
219 """获取峰值内存"""
220 return self._peak_memory_mb
222 def suggest_gc(self, threshold_mb: int = 500) -> bool:
223 """建议是否进行垃圾回收"""
224 current = self.get_current_memory_mb()
225 if current > threshold_mb:
226 import gc
227 gc.collect()
228 return True
229 return False
232# 全局性能监控实例
233performance_monitor = PerformanceMonitor()
234query_optimizer = QueryOptimizer()
235memory_optimizer = MemoryOptimizer()