mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 01:10:23 +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">
|
<script setup lang="ts">
|
||||||
import type { ProxyNode } from '@/api/proxy-nodes'
|
import type { ProxyNode } from '@/api/proxy-nodes'
|
||||||
import {
|
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
||||||
Tooltip,
|
|
||||||
TooltipContent,
|
|
||||||
TooltipProvider,
|
|
||||||
TooltipTrigger,
|
|
||||||
} from '@/components/ui'
|
|
||||||
import { Cpu } from 'lucide-vue-next'
|
import { Cpu } from 'lucide-vue-next'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
@@ -77,7 +72,10 @@ function formatNumber(n: number) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TooltipProvider v-if="showHardwareInfo">
|
<TooltipProvider
|
||||||
|
v-if="showHardwareInfo"
|
||||||
|
:delay-duration="0"
|
||||||
|
>
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<button
|
<button
|
||||||
@@ -97,7 +95,7 @@ function formatNumber(n: number) {
|
|||||||
v-if="hardwareRows.length === 0"
|
v-if="hardwareRows.length === 0"
|
||||||
class="text-muted-foreground"
|
class="text-muted-foreground"
|
||||||
>
|
>
|
||||||
No hardware info reported.
|
暂无硬件信息上报
|
||||||
</div>
|
</div>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -236,7 +236,7 @@ def validate_and_extract_model_mappings(
|
|||||||
return True, None, mappings
|
return True, None, mappings
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=2000)
|
@lru_cache(maxsize=512)
|
||||||
def _compile_pattern_cached(pattern: str) -> regex.Pattern | None:
|
def _compile_pattern_cached(pattern: str) -> regex.Pattern | None:
|
||||||
"""
|
"""
|
||||||
编译正则模式(带 LRU 缓存)
|
编译正则模式(带 LRU 缓存)
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ except ImportError: # pragma: no cover
|
|||||||
tiktoken = None
|
tiktoken = None
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=256)
|
@lru_cache(maxsize=32)
|
||||||
def _get_encoder_cached(model: str) -> Any:
|
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)
|
yield from _iter_ast_nodes(child)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache(maxsize=2048)
|
@lru_cache(maxsize=256)
|
||||||
def _validate_expression_cached(expression: str) -> ast.Expression:
|
def _validate_expression_cached(expression: str) -> ast.Expression:
|
||||||
"""
|
"""
|
||||||
Parse + validate an expression and cache the resulting AST.
|
Parse + validate an expression and cache the resulting AST.
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ from __future__ import annotations
|
|||||||
|
|
||||||
import json
|
import json
|
||||||
import re
|
import re
|
||||||
|
from collections import deque
|
||||||
from collections.abc import AsyncIterator
|
from collections.abc import AsyncIterator
|
||||||
from typing import Any
|
from typing import Any
|
||||||
|
|
||||||
@@ -108,8 +109,13 @@ class StreamUsageTracker:
|
|||||||
"stop_sequence": None,
|
"stop_sequence": None,
|
||||||
"usage": {},
|
"usage": {},
|
||||||
}
|
}
|
||||||
self.response_chunks = [] # 保存所有原始响应块
|
self.response_chunks = [] # 保存解析后的响应块
|
||||||
self.raw_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
|
self.start_time = None
|
||||||
@@ -133,6 +139,15 @@ class StreamUsageTracker:
|
|||||||
self.error_message = None # 错误消息(如果有)
|
self.error_message = None # 错误消息(如果有)
|
||||||
self.attempt_id = attempt_id
|
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:
|
def set_error_status(self, status_code: int, error_message: str) -> None:
|
||||||
"""
|
"""
|
||||||
设置错误状态
|
设置错误状态
|
||||||
@@ -275,7 +290,7 @@ class StreamUsageTracker:
|
|||||||
data = json.loads(data_str)
|
data = json.loads(data_str)
|
||||||
|
|
||||||
if isinstance(data, dict):
|
if isinstance(data, dict):
|
||||||
self.response_chunks.append(data)
|
self._append_response_chunk(data)
|
||||||
try:
|
try:
|
||||||
self._update_complete_response(data)
|
self._update_complete_response(data)
|
||||||
except Exception as update_error:
|
except Exception as update_error:
|
||||||
@@ -357,7 +372,7 @@ class StreamUsageTracker:
|
|||||||
|
|
||||||
# 更新完整响应(如果有数据)
|
# 更新完整响应(如果有数据)
|
||||||
if chunk.data:
|
if chunk.data:
|
||||||
self.response_chunks.append(chunk.data)
|
self._append_response_chunk(chunk.data)
|
||||||
try:
|
try:
|
||||||
self._update_complete_response(chunk.data)
|
self._update_complete_response(chunk.data)
|
||||||
except Exception as update_error:
|
except Exception as update_error:
|
||||||
@@ -635,14 +650,21 @@ class StreamUsageTracker:
|
|||||||
# 否则使用原始字节流(用于错误诊断,如403 HTML响应)
|
# 否则使用原始字节流(用于错误诊断,如403 HTML响应)
|
||||||
if self.response_chunks:
|
if self.response_chunks:
|
||||||
# 正常情况:成功解析的SSE JSON响应
|
# 正常情况:成功解析的SSE JSON响应
|
||||||
response_body = {
|
stored_chunks = len(self.response_chunks)
|
||||||
"chunks": self.response_chunks,
|
total_chunks = self.response_chunks_count
|
||||||
"metadata": {
|
metadata = {
|
||||||
"stream": True,
|
"stream": True,
|
||||||
"total_chunks": len(self.response_chunks),
|
"total_chunks": total_chunks,
|
||||||
|
"stored_chunks": stored_chunks,
|
||||||
"content_length": len(self.accumulated_content),
|
"content_length": len(self.accumulated_content),
|
||||||
"response_time_ms": response_time_ms,
|
"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": metadata,
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
# 错误情况:无法解析为JSON(如HTML错误页面)
|
# 错误情况:无法解析为JSON(如HTML错误页面)
|
||||||
|
|||||||
Reference in New Issue
Block a user