mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-18 06:15:51 +00:00
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:
@@ -1829,6 +1829,9 @@ async function* queryModel(
|
||||
let ttftMs = 0
|
||||
let partialMessage: BetaMessage | undefined
|
||||
const contentBlocks: (BetaContentBlock | ConnectorTextBlock)[] = []
|
||||
// Accumulate streaming deltas in arrays to avoid O(n²) string concatenation.
|
||||
// Joined and assigned to contentBlock fields at content_block_stop.
|
||||
const streamingDeltas = new Map<number, string[]>()
|
||||
let usage: NonNullableUsage = EMPTY_USAGE
|
||||
let costUSD = 0
|
||||
let stopReason: BetaStopReason | null = null
|
||||
@@ -2115,6 +2118,8 @@ async function* queryModel(
|
||||
}
|
||||
break
|
||||
}
|
||||
// Initialize delta accumulator for this content block
|
||||
streamingDeltas.set(part.index, [])
|
||||
break
|
||||
case 'content_block_delta': {
|
||||
const contentBlock = contentBlocks[part.index]
|
||||
@@ -2144,8 +2149,9 @@ async function* queryModel(
|
||||
})
|
||||
throw new Error('Content block is not a connector_text block')
|
||||
}
|
||||
;(contentBlock as { connector_text: string }).connector_text +=
|
||||
delta.connector_text
|
||||
streamingDeltas
|
||||
.get(part.index)
|
||||
?.push(delta.connector_text as string)
|
||||
} else {
|
||||
switch (delta.type) {
|
||||
case 'citations_delta':
|
||||
@@ -2175,7 +2181,9 @@ async function* queryModel(
|
||||
})
|
||||
throw new Error('Content block input is not a string')
|
||||
}
|
||||
contentBlock.input += delta.partial_json
|
||||
streamingDeltas
|
||||
.get(part.index)
|
||||
?.push(delta.partial_json as string)
|
||||
break
|
||||
case 'text_delta':
|
||||
if (contentBlock.type !== 'text') {
|
||||
@@ -2189,7 +2197,7 @@ async function* queryModel(
|
||||
})
|
||||
throw new Error('Content block is not a text block')
|
||||
}
|
||||
;(contentBlock as { text: string }).text += delta.text
|
||||
streamingDeltas.get(part.index)?.push(delta.text!)
|
||||
break
|
||||
case 'signature_delta':
|
||||
if (
|
||||
@@ -2224,8 +2232,7 @@ async function* queryModel(
|
||||
})
|
||||
throw new Error('Content block is not a thinking block')
|
||||
}
|
||||
;(contentBlock as { thinking: string }).thinking +=
|
||||
delta.thinking
|
||||
streamingDeltas.get(part.index)?.push(delta.thinking!)
|
||||
break
|
||||
}
|
||||
}
|
||||
@@ -2257,6 +2264,32 @@ async function* queryModel(
|
||||
})
|
||||
throw new Error('Message not found')
|
||||
}
|
||||
// Join accumulated streaming deltas into the contentBlock fields
|
||||
// to avoid O(n²) string concatenation during streaming.
|
||||
const deltas = streamingDeltas.get(part.index)
|
||||
if (deltas && deltas.length > 0) {
|
||||
const joined = deltas.join('')
|
||||
switch (contentBlock.type) {
|
||||
case 'text':
|
||||
;(contentBlock as { text: string }).text = joined
|
||||
break
|
||||
case 'thinking':
|
||||
;(contentBlock as { thinking: string }).thinking = joined
|
||||
break
|
||||
case 'tool_use':
|
||||
case 'server_tool_use':
|
||||
contentBlock.input = joined
|
||||
break
|
||||
default:
|
||||
if ((contentBlock.type as string) === 'connector_text') {
|
||||
;(
|
||||
contentBlock as { connector_text: string }
|
||||
).connector_text = joined
|
||||
}
|
||||
break
|
||||
}
|
||||
streamingDeltas.delete(part.index)
|
||||
}
|
||||
const m: AssistantMessage = {
|
||||
message: {
|
||||
...partialMessage,
|
||||
|
||||
Reference in New Issue
Block a user