가비지 컬렉션 지터(GC Jitter)란 무엇인가?
먼저 용어를 정의해 보겠습니다:
지터(Jitter) = 지연 시간의 불안정한 변동
시스템이 평소에 다음과 같은 응답 시간을 가진다고 가정해 봅시다:
2ms
2ms
2ms
2ms
2ms
어느 순간 갑자기 다음과 같이 변한다면:
2ms
2ms
180ms ← 갑작스러운 증가
2ms
2ms
이 "갑작스러운 증가"가 바로 지터입니다.
가비지 컬렉션 지터는 무엇인가?
가비지 컬렉터(GC)가 실행될 때 다음과 같은 과정이 발생합니다:
- 스레드 일시 중단(Stop-The-World)
- 객체 그래프 스캔
- 마킹
- 메모리 정리
- 해제
이 과정에서:
비즈니스 스레드가 일시 중단될 수 있습니다
이로 인해:
일부 요청의 응답 시간이 비정상적으로 길어집니다
이것이 바로 **가비지 컬렉션 지터(GC Jitter)**입니다.
꼬리 지연 시간(Tail Latency)이란 무엇인가?
100만 개의 요청이 있다고 가정해 봅시다.
통계 결과는 다음과 같습니다:
- 99% 요청: 2ms
- 0.9% 요청: 5ms
- 0.09% 요청: 10ms
- 0.01% 요청: 200ms
그러면 200ms는:
꼬리 지연 시간(Tail Latency)
고성능 시스템에서는 더 중요하게 다음을 관찰합니다:
P99
P99.9
P99.99
평균값이 아닙니다.
이유는:
시스템의 진짜 문제는 평균이 아니라 가장 느린 0.1%에 있습니다.
가비지 컬렉션 지터가 꼬리 지연 시간을 유발하는 이유
고주파 시스템을 상상해 봅시다:
- 초당 50,000개 요청 처리
- 각 요청은 1ms 소요
어느 순간:
GC 트리거
100ms 일시 중단
이 100ms 동안 모든 요청이 쌓입니다.
결과:
- 일부 요청은 100ms 지연
- 일부는 80ms 지연
- 일부는 50ms 지연
결과적으로:
꼬리 지연 시간이 갑자기 증가
GC가 단 한 번만 발생해도 통계 데이터를 오염시킵니다.
고주문 거래 시스템이 GC 언어를 거의 사용하지 않는 이유
고주문 거래 시스템의 특징은:
- 나노초 단위 지연
- 마이크로초 단위 변동도 심각한 문제
- 지연의 불안정성이 높은 지연보다 더 무서움
가정해 봅시다:
- 평균 지연 3 마이크로초
- 가끔 10 밀리초
이 10 밀리초는:
시장이 이미 변했음
가격이 이미 뛰었음
기회가 이미 사라졌음
금융 시장에서:
10ms는 수백만 원을 벌 수도 있고 잃을 수도 있습니다.
GC의 근본 문제: 예측 불가능성
GC는 다음과 같은 경우에도:
- Concurrent GC
- Low latency GC
- Server GC
여전히 다음과 같은 특성이 있습니다:
예측 불가능한 중단 지점
고주문 거래는 다음을 요구합니다:
엄격한 시간 결정성
C++이 더 적합한 이유
C++은 다음과 같은 이유로 더 적합합니다:
- GC가 없음
- 전역 중단이 없음
- 해제가 결정적(RAII)
- 힙 할당을 완전히 피할 수 있음
- 메모리 풀 사용 가능
- Lock-free 설계 가능
이는 다음을 의미합니다:
지연 분포가 더 부드러움
꼬리가 더 깨끗함
더 직관적인 비유
레이싱을 운전한다고 상상해 봅시다.
C# + GC는 무엇과 같을까요?
차는 빠르지만 가끔 자동으로 브레이크가 밟힙니다.
C++은 무엇과 같을까요?
차를 완전히 제어할 수 있습니다.
일반 운전에서는:
GC는 문제가 되지 않습니다.
F1 레이스에서는:
자동 브레이크는 재앙입니다.
공정하게 말하자면
현대 .NET은 다음과 같은 기능을 제공합니다:
- Low latency GC
- Span<T>
- stackalloc
- ArrayPool
- Server GC
많은 시나리오에서 이미 매우 우수합니다.
많은 금융 시스템도 다음과 같은 구조를 사용합니다:
- C++으로 매칭 코어 구현
- C#으로 주변 시스템 구현
핵심 요약
가비지 컬렉션 지터 = 가비지 수집으로 인한 지연 변동
꼬리 지연 시간 = 가장 느린 요청 지연 시간
고주문 거래 시스템이 GC 언어를 사용하지 않는 이유:
요구 사항:
결정성 > 평균 성능
안정성 > 개발 효율성
고주문 거래 배경과 연결
현재 다음과 같은 작업을 하고 있습니다:
- 고주문 거래 데이터
- 실시간 차트
- 대량 데이터 스트림
미래에 다음과 같은 작업을 한다면:
- 실시간 알고리즘 코어
- 실시간 신호 처리
- 저 지연 응답
다음을 시작하게 될 것입니다:
지연 분포
P99
P999
이때 다음을 진정으로 이해하게 될 것입니다:
왜 C++의 결정성이 중요한지