본문으로 건너뛰기

[gradio] Gradio SSE 라우트의 폴링 제거를 통한 성능 최적화

PR 링크: gradio-app/gradio#13046 상태: Merged | 변경: +1059 / -146

들어가며

Gradio는 실시간 데이터 스트리밍을 위해 SSE(Server-Sent Events)를 사용합니다. 기존 구현에서는 클라이언트에게 데이터를 전달하기 위해 queue.get_nowait()를 호출하고, 데이터가 없을 경우 asyncio.sleep()을 통해 주기적으로 상태를 확인하는 '폴링(Polling)' 방식을 사용하고 있었습니다. 이 방식은 동시 접속자가 많아질수록 서버의 CPU 자원을 불필요하게 소모하고, 응답 지연 시간(Latency)을 증가시키는 주범이었습니다. 본 PR은 이 폴링 메커니즘을 제거하고 asyncio.Queue의 비동기 대기 기능을 활용하여 성능을 대폭 개선했습니다.

코드 분석

1. gradio/queueing.py: 동기 큐에서 비동기 큐로 전환

기존 ThreadQueue는 멀티스레드 환경에는 적합하지만, 비동기 이벤트 루프 내에서 효율적인 대기를 지원하지 못했습니다. 이를 asyncio.Queue로 교체하여 이벤트 발생 시 즉시 깨어날 수 있도록 변경했습니다.

# Before
from queue import Queue as ThreadQueue
self.pending_messages_per_session: LRUCache[str, ThreadQueue[EventMessage]] = LRUCache(2000)

# After
from asyncio import Queue as AsyncQueue
self.pending_messages_per_session: LRUCache[str, AsyncQueue[EventMessage]] = AsyncQueue(2000)

2. gradio/routes.py: 폴링 제거 및 비동기 대기 도입

가장 핵심적인 변경사항입니다. asyncio.sleep()을 반복 호출하던 루프를 제거하고, await messages.get()을 통해 메시지가 도착할 때까지 비동기적으로 대기하도록 수정했습니다.

# Before
try:
    message = messages.get_nowait()
except EmptyQueue:
    await asyncio.sleep(check_rate)

# After
message = await asyncio.wait_for(messages.get(), timeout=10)

또한, 하트비트(Heartbeat) 기능을 별도의 asyncio.create_task로 분리하여, 메인 스트림 로직이 메시지 대기에만 집중할 수 있도록 구조를 개선했습니다.

왜 이게 좋은가

이번 최적화의 핵심은 'Busy Waiting'에서 'Event-Driven' 방식으로의 전환입니다. 이전에는 100명의 동시 접속자가 있을 때, 각 요청이 0.001초~0.05초마다 큐를 확인하며 불필요한 컨텍스트 스위칭을 유발했습니다.

결과적으로 100명의 동시 접속자 환경에서 echo_text 앱의 SSE 오버헤드가 329ms에서 48ms로 약 6.9배 감소하는 성과를 거두었습니다. 이는 서버 자원 효율성을 극대화하여 더 많은 사용자를 수용할 수 있는 기반이 됩니다.

리뷰어 피드백 반영

리뷰 과정에서 heartbeat 태스크가 제대로 정리되지 않을 가능성이 제기되었습니다. 이에 따라 향후 finally 블록을 통해 태스크를 명시적으로 취소(cancel)하는 로직을 추가하여 리소스 누수를 방지하는 방향으로 논의가 진행되었습니다.

교훈

  1. I/O Bound 작업에서는 폴링을 피하라: 비동기 프로그래밍 환경에서는 sleep을 통한 폴링보다 QueueEvent 객체를 통한 대기 방식이 훨씬 효율적입니다.
  2. 벤치마크의 중요성: 이번 개선은 단순히 코드를 바꾼 것이 아니라, 다양한 동시성 티어(1, 10, 100)에서의 성능 데이터를 기반으로 검증되었습니다. 최적화 전후의 수치 비교는 기술적 의사결정의 강력한 근거가 됩니다.

참고 자료

⚠️ 알림: 이 분석은 AI가 실제 코드 diff를 기반으로 작성했습니다.

댓글

관련 포스트

PR Analysis 의 다른글