mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-01 17:00:21 +08:00
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:
@@ -1,11 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import type { ProxyNode } from '@/api/proxy-nodes'
|
||||
import {
|
||||
Tooltip,
|
||||
TooltipContent,
|
||||
TooltipProvider,
|
||||
TooltipTrigger,
|
||||
} from '@/components/ui'
|
||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||
import { Cpu } from 'lucide-vue-next'
|
||||
import { computed } from 'vue'
|
||||
|
||||
@@ -77,7 +72,10 @@ function formatNumber(n: number) {
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<TooltipProvider v-if="showHardwareInfo">
|
||||
<TooltipProvider
|
||||
v-if="showHardwareInfo"
|
||||
:delay-duration="0"
|
||||
>
|
||||
<Tooltip>
|
||||
<TooltipTrigger as-child>
|
||||
<button
|
||||
@@ -97,7 +95,7 @@ function formatNumber(n: number) {
|
||||
v-if="hardwareRows.length === 0"
|
||||
class="text-muted-foreground"
|
||||
>
|
||||
No hardware info reported.
|
||||
暂无硬件信息上报
|
||||
</div>
|
||||
<template v-else>
|
||||
<div
|
||||
|
||||
@@ -236,7 +236,7 @@ def validate_and_extract_model_mappings(
|
||||
return True, None, mappings
|
||||
|
||||
|
||||
@lru_cache(maxsize=2000)
|
||||
@lru_cache(maxsize=512)
|
||||
def _compile_pattern_cached(pattern: str) -> regex.Pattern | None:
|
||||
"""
|
||||
编译正则模式(带 LRU 缓存)
|
||||
|
||||
@@ -22,7 +22,7 @@ except ImportError: # pragma: no cover
|
||||
tiktoken = None
|
||||
|
||||
|
||||
@lru_cache(maxsize=256)
|
||||
@lru_cache(maxsize=32)
|
||||
def _get_encoder_cached(model: str) -> Any:
|
||||
"""全局编码器缓存。
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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错误页面)
|
||||
|
||||
Reference in New Issue
Block a user