[Open WebUI] TTS 문장 파싱을 showCallOverlay 가드로 감싸 불필요한 O(n^2) 연산 제거
PR 링크: open-webui/open-webui#22195 상태: Merged | 변경: +58 / -52
들어가며
Open WebUI의 스트리밍 이벤트 핸들러는 매 토큰마다 getMessageContentParts()와 removeAllDetails()를 호출하여 TTS(텍스트 음성 변환)를 위한 문장을 추출합니다. 이 함수들은 누적된 전체 메시지 내용에 대해 여러 번의 정규식 패스를 수행하므로, 응답 전체에 걸쳐 O(n^2) 복잡도가 됩니다. 그런데 이 이벤트의 유일한 소비자는 CallOverlay.svelte이며, 이 컴포넌트는 showCallOverlay가 true일 때만 마운트됩니다. 대다수 사용자에게 이 파싱은 리스너 없이 실행되는 순수한 낭비입니다.
핵심 코드 분석
Before: 항상 TTS 파싱 실행
// 매 스트리밍 토큰마다 실행
const messageContentParts = getMessageContentParts(
removeAllDetails(message.content),
$config?.audio?.tts?.split_on ?? 'punctuation'
);
messageContentParts.pop();
if (messageContentParts.length > 0 &&
messageContentParts[messageContentParts.length - 1] !== message.lastSentence) {
message.lastSentence = messageContentParts[messageContentParts.length - 1];
eventTarget.dispatchEvent(new CustomEvent('chat', { ... }));
}
After: showCallOverlay 가드 적용
// 음성 통화 오버레이가 활성일 때만 파싱
if ($showCallOverlay) {
const messageContentParts = getMessageContentParts(
removeAllDetails(message.content),
$config?.audio?.tts?.split_on ?? 'punctuation'
);
messageContentParts.pop();
if (messageContentParts.length > 0 &&
messageContentParts[messageContentParts.length - 1] !== message.lastSentence) {
message.lastSentence = messageContentParts[messageContentParts.length - 1];
eventTarget.dispatchEvent(new CustomEvent('chat', { ... }));
}
}
이 패턴이 3곳의 TTS 파싱 블록 모두에 적용되었습니다.
왜 이게 좋은가
- 대다수 사용자에게 즉각적 개선: 음성 통화 기능을 사용하지 않는 사용자(대부분)에게 매 토큰마다 수행되던 정규식 파싱이 완전히 제거됩니다.
- O(n^2) -> O(1): 비활성 상태에서
removeAllDetails()와getMessageContentParts()의 다중 정규식 패스가 사라집니다. - 기능 보존:
showCallOverlay가 활성이면 기존과 동일하게 동작합니다. - 단순한 조건문 하나: if 가드 하나로 세 곳의 비용이 높은 코드 블록을 모두 보호합니다.
참고 자료
관련 포스트
- [Open WebUI] CodespanToken에서 JS 트랜지션을 CSS 애니메이션으로 교체하여 메인 스레드 부하 제거
- [Open WebUI] CodeEditor에서 EditorView 미해제로 인한 메모리 누수 수정
- [Open WebUI] UserMessage에서 JSON 직렬화 대신 structuredClone과 빠른 경로 비교 적용
- [Open WebUI] JSON.parse(JSON.stringify()) 를 structuredClone으로 교체
- [Open WebUI] 스트리밍 중 scrollToBottom을 rAF로 배치 처리하여 불필요한 리플로우 제거
PR Analysis 의 다른글
- 이전글 [Open WebUI] 스트리밍 중 동일 콘텐츠의 중복 마크다운 파싱을 캐시로 방지
- 현재글 : [Open WebUI] TTS 문장 파싱을 showCallOverlay 가드로 감싸 불필요한 O(n^2) 연산 제거
- 다음글 [Open WebUI] APIKeyRestrictionMiddleware를 순수 ASGI로 전환하여 스트리밍 오버헤드 제거
댓글