perf: 降低 lru_cache 上限并限制流式响应块内存占用

- 缩减 model_permissions / tiktoken / formula_engine 的 lru_cache maxsize
- StreamUsageTracker 响应块增加 4MB 大小限制,超限后只计数不存储
- raw_chunks 改用 deque(maxlen=50) 避免无限增长
- HardwareTooltip 导入路径修正、tooltip 延迟归零、文案中文化
This commit is contained in:
fawney19
2026-02-12 11:41:42 +08:00
parent 483d536e2c
commit be430ebdde
5 changed files with 41 additions and 21 deletions

View File

@@ -71,7 +71,7 @@ def _iter_ast_nodes(node: ast.AST) -> Iterable[ast.AST]:
yield from _iter_ast_nodes(child)
@lru_cache(maxsize=2048)
@lru_cache(maxsize=256)
def _validate_expression_cached(expression: str) -> ast.Expression:
"""
Parse + validate an expression and cache the resulting AST.

View File

@@ -7,6 +7,7 @@ from __future__ import annotations
import json
import re
from collections import deque
from collections.abc import AsyncIterator
from typing import Any
@@ -108,8 +109,13 @@ class StreamUsageTracker:
"stop_sequence": None,
"usage": {},
}
self.response_chunks = [] # 保存所有原始响应块
self.raw_chunks = [] # 保存所有原始字节流(用于错误诊断
self.response_chunks = [] # 保存解析后的响应块
self.response_chunks_count = 0 # 响应块总计数(含被丢弃的
self.response_chunks_size = 0 # 响应块累计序列化大小(字节)
self._response_chunks_max_size = 4 * 1024 * 1024 # 4MB留余量给 truncate_body 的 5MB 上限
self.raw_chunks: deque[str | bytes] = deque(
maxlen=50
) # 仅保留最后50个原始chunk用于错误诊断
# 时间跟踪
self.start_time = None
@@ -133,6 +139,15 @@ class StreamUsageTracker:
self.error_message = None # 错误消息(如果有)
self.attempt_id = attempt_id
def _append_response_chunk(self, data: dict[str, Any]) -> None:
"""追加响应块,超过大小限制后只计数不存储"""
self.response_chunks_count += 1
if self.response_chunks_size < self._response_chunks_max_size:
chunk_size = len(json.dumps(data, ensure_ascii=False))
self.response_chunks_size += chunk_size
if self.response_chunks_size <= self._response_chunks_max_size:
self.response_chunks.append(data)
def set_error_status(self, status_code: int, error_message: str) -> None:
"""
设置错误状态
@@ -275,7 +290,7 @@ class StreamUsageTracker:
data = json.loads(data_str)
if isinstance(data, dict):
self.response_chunks.append(data)
self._append_response_chunk(data)
try:
self._update_complete_response(data)
except Exception as update_error:
@@ -357,7 +372,7 @@ class StreamUsageTracker:
# 更新完整响应(如果有数据)
if chunk.data:
self.response_chunks.append(chunk.data)
self._append_response_chunk(chunk.data)
try:
self._update_complete_response(chunk.data)
except Exception as update_error:
@@ -635,14 +650,21 @@ class StreamUsageTracker:
# 否则使用原始字节流用于错误诊断如403 HTML响应
if self.response_chunks:
# 正常情况成功解析的SSE JSON响应
stored_chunks = len(self.response_chunks)
total_chunks = self.response_chunks_count
metadata = {
"stream": True,
"total_chunks": total_chunks,
"stored_chunks": stored_chunks,
"content_length": len(self.accumulated_content),
"response_time_ms": response_time_ms,
}
if stored_chunks < total_chunks:
metadata["truncated"] = True
metadata["dropped_chunks"] = total_chunks - stored_chunks
response_body = {
"chunks": self.response_chunks,
"metadata": {
"stream": True,
"total_chunks": len(self.response_chunks),
"content_length": len(self.accumulated_content),
"response_time_ms": response_time_ms,
},
"metadata": metadata,
}
else:
# 错误情况无法解析为JSON如HTML错误页面