From 69ae036f08ace389d458b0b1f593e761c24c3838 Mon Sep 17 00:00:00 2001 From: JOJO <1498581755@qq.com> Date: Fri, 29 May 2026 13:55:54 +0800 Subject: [PATCH] perf(status): defer docker stats on startup --- core/web_terminal.py | 11 +++++------ server/status.py | 4 +++- static/src/stores/resource.ts | 25 +++++++++++++++++++------ 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/core/web_terminal.py b/core/web_terminal.py index fe150ae..a522e36 100644 --- a/core/web_terminal.py +++ b/core/web_terminal.py @@ -345,9 +345,6 @@ class WebTerminal(MainTerminal): if self.terminal_manager: terminal_status = self.terminal_manager.list_terminals() - # 新增:对话状态 - conversation_stats = self.context_manager.get_conversation_statistics() - # 构建状态信息 limit_bytes = getattr(self, "project_storage_limit_bytes", None) status = { @@ -384,9 +381,11 @@ class WebTerminal(MainTerminal): # 新增:对话状态 "conversation": { "current_id": self.context_manager.current_conversation_id, - "total_conversations": conversation_stats.get('total_conversations', 0), - "total_messages": conversation_stats.get('total_messages', 0), - "total_tools": conversation_stats.get('total_tools', 0) + # 首屏不再同步计算全量对话统计;统计面板按需调用 + # /api/conversations/statistics,避免刷新时读取所有历史对话文件。 + "total_conversations": 0, + "total_messages": 0, + "total_tools": 0 } } status["todo_list"] = self.context_manager.get_todo_snapshot() diff --git a/server/status.py b/server/status.py index 03adee4..991bb5f 100644 --- a/server/status.py +++ b/server/status.py @@ -147,7 +147,9 @@ def get_status(terminal, workspace, username): status['project_path'] = str(workspace.project_path) phase_started_at = time.perf_counter() try: - status['container'] = container_manager.get_container_status(username) + # 首屏状态只需要容器是否存在/运行等轻量信息;Docker stats 很慢, + # 由 /api/container-status 在用量面板需要时单独拉取。 + status['container'] = container_manager.get_container_status(username, include_stats=False) except Exception as exc: status['container'] = {"success": False, "error": str(exc)} log_conn_diag(f"status container-status-failed user={username} error={exc}") diff --git a/static/src/stores/resource.ts b/static/src/stores/resource.ts index 6c3618f..1b0c009 100644 --- a/static/src/stores/resource.ts +++ b/static/src/stores/resource.ts @@ -54,6 +54,8 @@ const buildDefaultQuota = (): UsageQuota => ({ const PROJECT_STORAGE_POLL_INTERVAL_MS = 60_000; const PROJECT_STORAGE_POLL_INTERVAL_MAX_MS = 300_000; +const CONTAINER_STATS_POLL_INTERVAL_MS = 5_000; +const CONTAINER_STATS_POLL_INTERVAL_MAX_MS = 30_000; export const useResourceStore = defineStore('resource', { state: () => ({ @@ -79,7 +81,7 @@ export const useResourceStore = defineStore('resource', { lastContainerSample: null as ContainerSample | null, containerStatsInFlight: false, containerStatsFailCount: 0, - containerStatsIntervalMs: 500, + containerStatsIntervalMs: CONTAINER_STATS_POLL_INTERVAL_MS, containerStatsTimer: null as ReturnType | null, projectStorageTimer: null as ReturnType | null, projectStorageInFlight: false, @@ -103,6 +105,11 @@ export const useResourceStore = defineStore('resource', { toggleTokenPanel() { console.log('[UI_DEBUG] toggleTokenPanel called, current state:', this.tokenPanelCollapsed, 'new state:', !this.tokenPanelCollapsed); this.tokenPanelCollapsed = !this.tokenPanelCollapsed; + if (this.tokenPanelCollapsed) { + this.stopContainerStatsPolling(); + } else { + this.startContainerStatsPolling(); + } }, async updateCurrentContextTokens(conversationId: string | null) { if (!conversationId) { @@ -236,14 +243,17 @@ export const useResourceStore = defineStore('resource', { this.updateContainerStatus(data.data || null); } this.containerStatsFailCount = 0; - if (this.containerStatsIntervalMs > 500) { - this._restartContainerStatsTimer(500); + if (this.containerStatsIntervalMs > CONTAINER_STATS_POLL_INTERVAL_MS) { + this._restartContainerStatsTimer(CONTAINER_STATS_POLL_INTERVAL_MS); } } catch (error) { console.warn('获取容器状态异常:', error); this.containerStatsFailCount += 1; if (this.containerStatsFailCount >= 3) { - const nextInterval = Math.min(this.containerStatsIntervalMs * 2, 10_000); + const nextInterval = Math.min( + this.containerStatsIntervalMs * 2, + CONTAINER_STATS_POLL_INTERVAL_MAX_MS + ); this._restartContainerStatsTimer(nextInterval); } } finally { @@ -257,8 +267,11 @@ export const useResourceStore = defineStore('resource', { if (this.containerStatsTimer) { return; } + if (this.tokenPanelCollapsed) { + return; + } this.containerStatsFailCount = 0; - this.containerStatsIntervalMs = 500; + this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS; this.pollContainerStats(); this.containerStatsTimer = setInterval(() => { this.pollContainerStats(); @@ -290,7 +303,7 @@ export const useResourceStore = defineStore('resource', { this.stopContainerStatsPolling(); } else { this.containerStatsFailCount = 0; - this.containerStatsIntervalMs = 500; + this.containerStatsIntervalMs = CONTAINER_STATS_POLL_INTERVAL_MS; this.startContainerStatsPolling(); } };