벤치마크

벤치마크 (Benchmarks)

가짜 OpenAI 엔드포인트에 대해 테스트한 LiteLLM Gateway (Proxy Server) 벤치마크예요.

LiteLLM Gateway는 1k RPS에서 8ms P95 지연 시간을 가집니다 (벤치마크 참고).

고처리량 프로파일: 50K~100K 토큰 프롬프트로 3,000 RPS

큰 프롬프트는 짧은 채팅 요청과 다른 게이트웨이 워크로드를 만듭니다. 토큰 카운팅, 예산 검사, 지출 추적, 메트릭 수집 모두 모델-프로바이더 호출 전이나 후에 발생하며, 높은 요청 볼륨에서 병목이 될 수 있어요.

이 벤치마크는 고처리량 배포 프로파일을 v1.101.0 과 비교합니다. 이 프로파일은 Rust 토큰 카운팅, 공유 데이터베이스 연결, 격리된 메트릭 및 지출 처리, 트래픽 기반 자동 스케일링을 결합합니다.

고처리량 프로파일은 아직 개발 중이며 nightly 빌드에서 제공됩니다. 이 결과는 완전한 프로파일의 가장 이른 사용 가능 버전을 사용한 것입니다.

출처: 문서

본문

결과

카테고리 지표 고처리량 프로파일 v1.101.0 변경
배포 게이트웨이 pods 33 132 4x 적음
pod당 workers 4 1
총 workers 132 132 동일
처리량 Requests/sec 3.00K 0.19K 16x
Tokens/sec 224.61M 6.92M 32x
예상 tokens/30 days 582.20T 17.94T 32x
신뢰성 HTTP 200 rate (Locust) 100.00% 92.07%
요청 지연 p50 30.581 ms 6.950 s 227x
p95 54.029 ms 27.451 s 508x
p99 91.645 ms 29.826 s 325x
첫 토큰까지 시간 p50 31.667 ms 9.400 s 297x

프로파일은 100% 클라이언트 가시 성공으로 전체 3,000 RPS 목표에 도달했습니다. 기준선은 약 190 RPS에 정착했고 92.07%의 요청에 성공 응답을 반환했습니다.

테스트 설정

테스트 차원 구성
로드 생성기 마스터 하나와 30개 workers가 있는 분산 Locust
트래픽 각각 초당 요청 하나인 3,000명의 시뮬레이션 사용자
요청 믹스 50K, 75K, 100K 토큰 프롬프트를 같은 비율로
스트리밍 요청의 50%
엔드포인트 max_tokens: 16/v1/chat/completions
인증 예산이 있는 가상 키 — 입장 토큰 카운팅과 예산 예약 실행됨
모델 응답 캐싱이 비활성화된 인프로세스 mock 모델
네트워크 경로 공개 AWS Application Load Balancer
클라이언트 타임아웃 60초
실행 시간 고처리량 프로파일: 24m 22s. 기준선: 5m 7s.

mock 모델은 게이트웨이 요청 경로를 활성 상태로 유지하면서 프로바이더 비용과 프로바이더 지연 시간을 제거합니다. 테스트는 인증, 예산, 토큰 카운팅, 지출 추적, 메트릭을 여전히 포함합니다.

두 배포 모두 총 132개 게이트웨이 workers를 실행하고 528 GiB 메모리를 요청했습니다. 고처리량 프로파일은 pod당 4개 workers로 33 pods를, 132 vCPU를 요청했습니다. 기준선은 pod당 worker 하나로 132 pods를, 264 vCPU를 요청했습니다.

무엇이 차이를 만들었나

아래 각 변경은 완전한 프로파일을 테스트하기 전에 개별적으로 측정되었습니다.

변경 고객 영향 측정 효과
Rust 입장 토큰 카운팅 디스패치 전에 큰 프롬프트를 세는 CPU 감소 50K/75K/100K 카운트가 46/53/100 ms에서 4.9/6.8/10.2 ms로 감소
pod당 PgBouncer 데이터베이스 연결이 worker마다 곱해지는 것 방지 Postgres가 1129 pods에 걸쳐 86175 연결 유지, 대기 PgBouncer 클라이언트 없음
지출 수집 sidecar 지출 처리를 추론 workers에서 분리 700 RPS에서 p99가 1.8 s에서 830 ms로 감소. 총 컴퓨팅은 거의 동일
메트릭 sidecar Prometheus 스크레이프를 추론 workers에서 분리 sidecar가 700 RPS에서 pod당 약 2 millicores 사용
더 높은 CPU burst 한도 pod의 모든 workers가 함께 스로틀링되는 것 방지 700 RPS에서 p99가 830 ms에서 670 ms로 감소
게이트웨이 keep-alive 스케일링 중 로드 밸런서 연결 유효 유지 ALB 생성 502 응답이 200 RPS 테스트에서 15에서 0으로 감소
RPS 및 TPS 자동 스케일링 CPU가 포화되기 전에 트래픽에 반응 200-user 로드 스텝 후 약 48초에 새 replicas 추가
입장 토큰 카운트 재사용 mock 테스트에서 같은 큰 스트리밍 프롬프트를 두 번 세는 것 방지 스트리밍 mock 요청이 비스트리밍 요청 약 30 ms 내에 완료

지표 읽는 방법

  • 초당 요청, 초당 토큰, 예상 토큰, 요청 지연 시간은 게이트웨이의 Prometheus 메트릭에서 나옵니다.
  • 첫 토큰까지 시간은 Locust에서 나오며, 요청 전송부터 첫 스트리밍 이벤트 수신까지의 시간을 측정합니다. 요청 업로드, 로드 밸런서, 게이트웨이 입장 작업을 포함합니다.
  • HTTP 200 비율은 게이트웨이에 도달하지 못한 실패를 포함하므로 Locust에서 나옵니다.

v1.101.0 실행에는 5,118개의 클라이언트 가시 실패가 있었습니다: 4,546개 클라이언트 타임아웃/연결 드롭, 457개 HTTP 504, 115개 HTTP 502. 게이트웨이는 이 요청들을 받지 못했으므로 자체 성공 메트릭은 100%를 보였지만 Locust는 92.07%를 보였습니다.

Locust 처리량을 읽을 때는 POST 행을 사용하세요. 각 스트리밍 요청은 TTFT 행도 만들므로, 스트리밍이 활성화되면 Locust Aggregated 행이 실제 요청보다 더 많은 항목을 셉니다.

벤치마크 범위

이것은 완전한 프로파일의 before-after 비교이며 단일 변수 테스트가 아닙니다. 배포는 다른 pod 형태를 사용했고 다른 길이로 실행되었습니다. 위 표의 개별 효과는 200~1,000 RPS의 별도 A/B 테스트에서 나옵니다.

인프로세스 mock 모델은 프로바이더 지연 시간을 제외합니다. 이 결과는 이 특정 트래픽 형태에 대한 게이트웨이 용량을 측정하며, 보편적인 프로덕션 크기 조정 지침으로 취급하지 마세요. worker 수, pod 리소스, HPA 목표를 고르기 전에 대표 워크로드를 측정하세요.

아래 섹션은 4 CPU / 8 GB 머신의 가짜 OpenAI 엔드포인트에 대한 짧은 요청 본문을 사용합니다. 이 큰 프롬프트 벤치마크와 직접 비교할 수 없습니다.

테스트에 사용된 머신 스펙

LiteLLM을 배포한 각 머신은 다음 스펙을 가졌습니다:

  • 4 CPU
  • 8GB RAM

구성

  • 데이터베이스: PostgreSQL. 크기 조정은 Database Sizing 참고
  • Redis: 미사용. 프로덕션에서 권장; Redis Sizing 참고
  • 로드 생성기: Locust, 1000명 사용자, 각 요청 사이 0.5s~1s 씩 생각 시간. 숫자를 자신의 실행과 비교하기 전에 Locust Settings 참고

2개 인스턴스 LiteLLM Proxy

이 테스트에서 기준 지연 특성은 fake-openai-endpoint에 대해 측정됩니다.

성능 메트릭

타입 이름 중앙값 (ms) 95%ile (ms) 99%ile (ms) 평균 (ms) 현재 RPS
POST /chat/completions 200 630 1200 262.46 1035.7
Custom LiteLLM Overhead Duration (ms) 12 29 43 14.74 1035.7
Aggregated 100 430 930 138.6 2071.4

4개 인스턴스

타입 이름 중앙값 (ms) 95%ile (ms) 99%ile (ms) 평균 (ms) 현재 RPS
POST /chat/completions 100 150 240 111.73 1170
Custom LiteLLM Overhead Duration (ms) 2 8 13 3.32 1170
Aggregated 77 130 180 57.53 2340

핵심 발견

  • LiteLLM 인스턴스를 2에서 4로 두 배로 늘리면 중앙값 지연이 절반: 200 ms → 100 ms.
  • 고백분위수 지연이 크게 감소: P95 630 ms → 150 ms, P99 1,200 ms → 240 ms.
  • workers를 CPU 수와 같게 설정하면 최적 성능.

네트워크 Mock으로 벤치마킹 설정

프록시 오버헤드를 벤치마킹하는 가장 빠른 방법은 network_mock 모드를 사용하는 것입니다. 이는 httpx transport 레이어에서 아웃바운드 요청을 가로채 캔 응답을 반환하므로 mock 프로바이더를 설정할 필요가 없어요.

  1. proxy config 생성:
model_list:
  - model_name: db-openai-endpoint
    litellm_params:
      model: openai/gpt-5.6-terra
      api_key: "sk-fake-key"
      api_base: "https://api.openai.com"

litellm_settings:
  network_mock: true
  callbacks: []
  num_retries: 0
  request_timeout: 30

general_settings:
  master_key: "sk-<your-litellm-master-key>"
  1. 프록시 시작:
litellm --config benchmark_config.yaml --port 4000 --num_workers 8
  1. 벤치마크 스크립트 실행:
python scripts/benchmark_mock.py --requests 2000 --max-concurrent 200 --runs 3

벤치마킹 스크립트는 여기에서 얻습니다.

이것은 실제 또는 가짜 프로바이더에 대한 네트워크 지연 없이 핫 경로의 순수 프록시 오버헤드를 측정합니다.

가짜 OpenAI 엔드포인트 설정

부하 테스트와 벤치마킹을 위해 가짜 OpenAI 프록시 서버를 사용할 수 있습니다. LiteLLM은 다음을 제공합니다:

  1. 호스티드 엔드포인트: https://exampleopenaiendpoint-production.up.railway.app/ 의 무료 호스티드 fake 엔드포인트 사용
  2. 셀프 호스티드: github.com/BerriAI/example_openai_endpoint 로 자체 가짜 OpenAI 프록시 서버 설정

테스트에 이 config를 사용하세요:

model_list:
  - model_name: "fake-openai-endpoint"
    litellm_params:
      model: openai/any
      api_base: https://exampleopenaiendpoint-production.up.railway.app/  # or your self-hosted endpoint
      api_key: "test"

/realtime API 벤치마크

가짜 realtime 엔드포인트에 대해 테스트한 /realtime 엔드포인트의 종단 간 지연 벤치마크예요.

성능 메트릭

지표
중앙값 지연 시간 59 ms
p95 지연 시간 67 ms
p99 지연 시간 99 ms
평균 지연 시간 63 ms
RPS 1,207

테스트 설정

카테고리 사양
부하 테스트 Locust: 1,000명 사용자, 0.5s~1s 생각 시간, 500 ramp-up
시스템 4 vCPUs, 8 GB RAM, 4 workers, 4 인스턴스
데이터베이스 PostgreSQL (Redis 미사용)

인프라 권장 사항

위 실행은 단일 PostgreSQL 인스턴스와 Redis 없이 수행되었는데, 이것은 프로덕션 구성이라기보다 벤치마크 구성입니다. 각 요청율의 인스턴스 크기, 확장 시 배포가 살아남는지 결정하는 연결 수학, AWS/Azure/GCP의 구체적인 관리 서비스 선택은 Database Sizing 및 Redis Sizing 참고. 함께 가는 게이트웨이 측 구성은 Production Best Practices 참고.

Locust 설정

  • 1000명 Users
  • 500 user Ramp Up
  • wait_time = between(0.5, 1) — 모든 사용자가 요청 사이 0.5s~1s 대기

이 숫자를 재현할 때 생각 시간이 중요한 이유

Locust 사용자는 응답을 기다리거나 자는 데 시간을 보냅니다. 평균 생각 시간 0.75s와 ~110ms 응답으로, 1000명 사용자 각각은 약 0.86s마다 요청 하나를 완료합니다. 따라서 실행은 ~1160 RPS를 제공하고 어느 순간 약 130개 요청을 진행 중으로 유지합니다. 위 지연 열이 설명하는 것은 사용자 수가 아니라 이 진행 중 깊이(in-flight depth)입니다.

생각 시간이 없는 폐쇄 루프 클라이언트는 다른 것을 측정합니다. 이전 것 반환 즉시 다음 요청을 보내는 1000개 동시 workers는 1000개 요청을 진행 중으로 유지하는데, 이는 이 실행들의 큐 깊이보다 약 8배입니다. 게이트웨이가 포화되면 처리량은 고정되고, Little's Law에 따라 각 클라이언트가 관찰하는 지연은 진행 중 요청 수 / 처리량 입니다. 따라서 같은 배포가, 같은 RPS에서, 클라이언트가 그만큼 더 많은 작업을 큐했기 때문에 약 8배 지연을 보고합니다. 지연과 동시성은 독립적이지 않으며, 둘 중 하나의 숫자도 다른 것 없이는 의미가 없습니다.

위 표와 비교하려면 0.5s~1s 생각 시간을 유지하거나, 클라이언트의 진행 중 요청 수를 약 130 근처로 유지하고 지연과 함께 보고하세요. RPS를 먼저 보고하는 것도 가치가 있습니다: 실행이 이 표보다 높은 RPS와 높은 지연을 보이면 게이트웨이가 이 벤치마크보다 빠르고 클라이언트가 더 깊이 큐잉하고 있는 것입니다.

LiteLLM 오버헤드 측정 방법

litellm의 모든 응답에는 x-litellm-overhead-duration-ms 헤더가 포함됩니다. 이는 LiteLLM Proxy가 추가한 지연 오버헤드(ms)입니다.

locust에서 이걸 측정하려면 다음 코드를 사용하세요:

import os
import uuid
from locust import HttpUser, task, between, events

# Custom metric to track LiteLLM overhead duration
overhead_durations = []

@events.request.add_listener
def on_request(request_type, name, response_time, response_length, response, context, exception, start_time, url, **kwargs):
    if response and hasattr(response, 'headers'):
        overhead_duration = response.headers.get('x-litellm-overhead-duration-ms')
        if overhead_duration:
            try:
                duration_ms = float(overhead_duration)
                overhead_durations.append(duration_ms)
                # Report as custom metric
                events.request.fire(
                    request_type="Custom",
                    name="LiteLLM Overhead Duration (ms)",
                    response_time=duration_ms,
                    response_length=0,
                )
            except (ValueError, TypeError):
                pass

class MyUser(HttpUser):
    wait_time = between(0.5, 1)  # Random wait time between requests

    def on_start(self):
        self.api_key = os.getenv('API_KEY', 'sk-<your-litellm-api-key>')
        self.client.headers.update({'Authorization': f'Bearer {self.api_key}'})

    @task
    def litellm_completion(self):
        # no cache hits with this
        payload = {
            "model": "db-openai-endpoint",
            "messages": [{"role": "user", "content": f"{uuid.uuid4()} This is a test there will be no cache hits and we'll fill up the context" * 150}],
            "user": "my-new-end-user-1"
        }
        response = self.client.post("chat/completions", json=payload)
        
        if response.status_code != 200:
            # log the errors in error.txt
            with open("error.txt", "a") as error_log:
                error_log.write(response.text + "\n")

LiteLLM vs Portkey 성능 비교

테스트 구성: 인스턴스당 4 CPUs, 8 GB RAM | 로드: 1k 동시 사용자, 500 ramp-up | 버전: Portkey v1.14.0 | LiteLLM v1.79.1-stable | 테스트 시간: 5분

멀티 인스턴스 (4×) 성능

지표 Portkey (no DB) LiteLLM (with DB) Comment
총 요청 293,796 312,405 LiteLLM이 더 높음
실패 요청 0 0 동일
중앙값 지연 100 ms 100 ms 동일
p95 지연 230 ms 150 ms LiteLLM이 더 낮음
p99 지연 500 ms 240 ms LiteLLM이 더 낮음
평균 지연 123 ms 111 ms LiteLLM이 더 낮음
현재 RPS 1,170.9 1,170 동일

지연 시간 메트릭은 낮을수록 좋고, 요청과 RPS는 높을수록 좋습니다.

기술적 인사이트

Portkey — 장점: 낮은 메모리 사용량, 최소한의 스파이크로 안정적인 지연. 단점: CPU 사용률이 ~40%로 한정되어 가용 컴퓨팅 리소스를 활용하지 못함, I/O timeout 장애 3회 발생.

LiteLLM — 장점: 가용 CPU 용량을 완전히 사용, 강력한 연결 처리와 초기 워밍업 스파이크 후 낮은 지연. 단점: 초기화 중과 요청당 메모리 사용량이 높음.

로깅 콜백

GCS Bucket 로깅

GCS Bucket 사용은 기본 Litellm Proxy와 비교해 지연, RPS에 영향이 없습니다.

지표 기본 Litellm Proxy GCS Bucket 로깅이 있는 LiteLLM Proxy
RPS 1133.2 1137.3
중앙값 지연 (ms) 140 138

LangSmith 로깅

LangSmith 사용은 기본 Litellm Proxy와 비교해 지연, RPS에 영향이 없습니다.

지표 기본 Litellm Proxy LangSmith가 있는 LiteLLM Proxy
RPS 1133.2 1135
중앙값 지연 (ms) 140 132

더 알아보기 (Learn more)