Python FastAPI vs Go Web Application 성능테스트 비교 영상 정리
https://youtu.be/CdkAMceuoBg?si=G2AxWUA9v1wIiuyd
FastAPI와 Go standard Library로 만든 Web Application의 성능 비교.
소스코드:
https://github.com/antonputra/tutorials/tree/231/lessons/231
tutorials/lessons/231 at 231 · antonputra/tutorials
DevOps Tutorials. Contribute to antonputra/tutorials development by creating an account on GitHub.
github.com
Test 1. Baseline
하드코딩으로 간단한 Objects를 만들어서 json으로 응답하는 예시.
측정 항목
- client side Latency: p99
- throughput: RPS 계산
- CPU / Memory Usage
- Error Rate (Availability)
- CPU throttling.
Test 2.
측정 항목
- Post 요청을 받았을 때, request Body 파싱 + UUID와 timestamp 생성 + Postgres에 record 저장
- DB 저장이 끝나면 Cache Set 진행. cache set에 걸리는 Latency (p90)
- cache는 Memcache 사용
- Postgres와 Memcache의 CPU 사용량, Connection Pool size 확인.
측정 환경
- memcached: AWS m7a.xlarge instance
- postgres: AWS 2xlarge EC2 instance
- EKS with 2 instance group
- 애플리케이션을 실행할 m7a.large
- Prometheus, Grafana, 부하를 발생시킬 client를 배포할 compute-optimized Graviton (c8g.4xlarge)
- 메모리가 딱히 필요하지 않으므로, general instance보다 비용이 약간 저렴하다고 함
Test 1 결과
다른 벤치마크 테스트에서도 그랬듯, Python의 CPU 사용량은 다른 어떤 애플리케이션 구현과 비교해도 높았다.
- Python의 경우 빠르게 p99 Latency가 증가. Golang 대비 2배 이상.
- 13000 TPS 무렵부터 fastAPI 앱의 RPS가 더 이상 증가하지 못한다.
- CPU usage가 full로 차면서, k8s의 CPU throttling이 잡히기 시작
- 25000 TPS 즈음에 Python 앱이 Fail 상태가 된다.
- availability 수치가 0으로 변경.
- 애플리케이션이 과부하됐을 때 발생하는 상황임.
- client의 request에 timeout 또는 500 status가 발생.
FastAPI의 성능이 Django보다 소폭 낫지만, 그렇게까지 큰 성능차이는 아닌 거 같다고.
- Golang 앱은 대략 62000 TPS까지 버티는 걸 볼 수 있음.
RPS: FastAPI는 13000 TPS를 넘지 못하지만, Golang은 62000 TPS까지 버텨냈다.
Latency: FastAPI는 fail 발생해서 latency가 뒤죽박죽인 반면, go는 낮고 안정적인 latency
CPU usage: FastAPI는 초반 10~15분만에 cpu 사용량을 100% 찍음. 따라서 cpu throttle이 전반적으로 많이 발생함.
Availability: ratio of successful request / # of all requests
Memory: go가 전체적으로 더 낮은 메모리를 사용하고, spike 튀는 지점은 app fail 발생할 때임.
cf. k8s Go application이라면, go user thread를 pod limit에 맞춰주는 게 좋다. 그래야 k8s 앱에서 cpu throttling이 발생하지 않음.
env:
- name: GOMAXPROC
valueFrom:
resourceFieldRef:
resource: limits.cpu
resources:
requests:
memory: 2Gi
cpu: 1500m
limits:
memory: 4Gi
cpu: 2000m
Test 2 결과
Connection Pool Size는 최대 500으로 설정해두었음.
- POST 요청이 오면 request body 파싱해서
- Postgres DB에 저장
- 저장한 데이터를 Memcached 에 Cache Set 한다.
overall: FastAPI는 테스트 시작 10여분 만에 limit에 도달한 반면, go는 limit 도달까지 1시간 걸림.
- DB latency, Cache Set, Request Latency도 Go가 훨씬 낮다.
- FastAPI의 RPS는 800을 넘지 못한다. Go의 경우 테스트에서는 한계점을 찾지 못함.
- go가 막판에 spike가 발생한 이유는 memcached가 떠 있는 linux box의 file descriptor limit을 낮게 설정했기 때문. 정상적으로 높여주면 TPS는 계속 올라간다.