fix: 优化内存峰值与 CPU 性能,降低 100-300MB 内存占用

- claude.ts: 流式字符串拼接从 O(n²) += 改为数组累积 join,消除 4 处热点
- Messages.tsx: 合并 3 组独立遍历为单次 pass(thinking/bash 查找、3-filter 链、divider/selectedIdx)
- HighlightedCode.tsx: ColorFile 实例添加模块级 LRU 缓存(50 条),避免重复创建
- screen.ts: StylePool 衍生缓存添加 1000 条上限淘汰,防止无界增长
- CompanionSprite.tsx: TICK_MS 从 500ms 提升至 1000ms,减少 setState 频率
- connection.ts: MCP stderr 缓冲从 64MB 降至 8MB
- stringUtils.ts: MAX_STRING_LENGTH 从 32MB 降至 2MB
- sessionStorage.ts: Transcript 写入队列添加 1000 条上限
- query.ts: spread 改 concat 减少一次数组拷贝
- PromptInputFooterLeftSide.tsx: 显示进程 pid 便于调试

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
claude-code-best
2026-05-02 00:45:03 +08:00
parent f484fc34c8
commit ef10ad2839
13 changed files with 397 additions and 81 deletions

View File

@@ -7,6 +7,12 @@ import sliceAnsi from '../utils/sliceAnsi.js';
import { countCharInString } from '../utils/stringUtils.js';
import { HighlightedCodeFallback } from './HighlightedCode/Fallback.js';
import { expectColorFile } from './StructuredDiff/colorDiff.js';
import type { ColorFile as ColorFileType } from 'color-diff-napi';
// Module-level LRU cache for ColorFile instances to avoid recreating
// them for the same (filePath, code) across component instances.
const colorFileCache = new Map<string, { colorFile: ColorFileType; code: string }>();
const COLOR_FILE_CACHE_MAX = 50;
type Props = {
code: string;
@@ -37,7 +43,22 @@ export const HighlightedCode = memo(function HighlightedCode({
if (!ColorFile) {
return null;
}
return new ColorFile(code, filePath);
const cacheKey = `${filePath}\0${code.length}`;
const cached = colorFileCache.get(cacheKey);
if (cached && cached.code === code) {
// Move to end (most recently used)
colorFileCache.delete(cacheKey);
colorFileCache.set(cacheKey, cached);
return cached.colorFile;
}
const instance = new ColorFile(code, filePath);
// Evict oldest entry if cache is full
if (colorFileCache.size >= COLOR_FILE_CACHE_MAX) {
const oldest = colorFileCache.keys().next().value;
if (oldest !== undefined) colorFileCache.delete(oldest);
}
colorFileCache.set(cacheKey, { colorFile: instance, code });
return instance;
}, [code, filePath, syntaxHighlightingDisabled]);
useEffect(() => {