Zettelkasten

python 3.11 이후부턴 gevent 성능이 악화될 수 있다.

·수정 2026.04.23·수정 1

요약

  • python 3.12 부턴 greenlet 사용하기 어려움

본문

Python 버전별 gevent 성능 벤치마크

Python 버전 업그레이드 시 gevent 스택 성능 영향을 측정하여 업그레이드 판단 근거를 확보하기 위한 실험.

실험 환경

항목
플랫폼 Docker linux/amd64 (프로덕션과 동일 아키텍처)
gevent 25.9.1 (3.9만 24.2.1)
greenlet 3.4.0 (3.9만 3.2.5)
반복 횟수 5회 (중앙값 기준)
실행일 2026-04-15

Mac ARM64에서 QEMU 에뮬레이션으로 실행되므로 절대값보다 버전 간 상대 비교가 의미 있음.

벤치마크 항목

벤치마크 측정 대상 파라미터
greenlet_switch 순수 greenlet.switch() 속도 200만 회 switch
gevent_socket_echo gevent TCP echo 처리량 100 클라이언트 x 200 메시지 (64B)
gevent_http_pool gevent HTTP RPS 2000 요청, 동시 50개

결과

greenlet context switch (us/op, 낮을수록 좋음)

3.9   ██████████                      0.506 μs  (baseline)
3.10  ████████████████                0.804 μs  +59%  ← 현재 버전
3.11  ███████████████                 0.763 μs  -5% vs 3.10
3.12  ███████████████████             0.966 μs  +20% vs 3.10
3.13  █████████████████               0.859 μs  +7% vs 3.10

TCP echo (msgs/sec, 높을수록 좋음)

3.9   █████████████████               44,898
3.10  ████████████████████            52,949  ← 현재 버전
3.11  ███████████████████             50,069  -5%
3.12  ██████████████████              46,333  -12%
3.13  ████████████████████            54,002  +2%

HTTP RPS (높을수록 좋음)

프로덕션에 가장 가까운 지표.

3.9   ████████████████                2,188
3.10  █████████████████               2,337  ← 현재 버전
3.11  ███████████████████             2,638  +13%
3.12  █████████████████               2,355  +1%
3.13  ███████████████████             2,568  +10%

종합

버전 greenlet switch HTTP RPS 판정
3.10 → 3.11 -5% (개선) +13% (개선) 업그레이드 추천
3.10 → 3.12 +20% (악화) +1% (무의미) 비추천
3.10 → 3.13 +7% (악화) +10% (개선) greenlet 불안정

분석

3.11이 좋은 이유

CPython 3.11의 specializing adaptive interpreter가 인터프리터 루프 자체를 최적화하여, greenlet switch 오버헤드를 상쇄하고도 HTTP RPS가 +13% 향상됨.

3.12에서 greenlet이 느려지는 이유

CPython 3.11부터 Python 프레임을 _PyInterpreterFrame이라는 경량 구조체로 재설계하기 시작함 (Faster CPython / PEP 659). greenlet은 C 스택을 통째로 swap하는 방식으로 동작하는데, 프레임 구조가 바뀌면서 context switch 시 추가 저장/복원 작업이 필요해짐.

3.11에서는 specializing adaptive interpreter의 성능 이득이 이 오버헤드를 상쇄하고 남았지만, 3.12에서 프레임 변경이 더 깊어지면서 (comprehension inlining, free-threading 준비 본격화) greenlet context switch 비용이 +20% 증가하고 상쇄가 불가능해짐.

이 변경은 free-threading(nogil) 준비를 위한 구조적 변화이므로 후속 버전에서도 해소되지 않음. (참고: gevent/gevent#1928)

3.12 HTTP RPS가 거의 차이 없는 이유

CPython 인터프리터 자체 성능 향상이 greenlet 저하를 딱 상쇄할 정도. 즉 gevent 스택의 이득이 0에 수렴하며, 버전이 올라갈수록 상황이 악화될 가능성이 높음.

결론

  • 3.11 업그레이드: gevent 유지한 채 성능 이득 확보 가능
  • 3.12+ 업그레이드: gevent → asyncio 전환이 선행되어야 함

3.11 업그레이드 시 블로커

  1. gunicorn 20.1.0 → 22.0.0+ 업그레이드
  2. django-mysql-geventpool 0.2.5 유지보수 중단 대응 (포크 교체 또는 django-db-geventpool)

참고

https://github.com/gevent/gevent/issues/1928 python 3.12부턴 cpython stack이 PyInterpreterFrame으로 관리된다. https://github.com/junha6316/gevent-pyver-benchmark