Per-core io_context Architecture

Shared-nothing 아키텍처가 Shared io_context(뮤텍스/Lock-Free) 모델 대비 코어 수에 비례하는 선형 확장을 달성하고, 고코어 서버에서 격차가 극대화됨을 증명하는 벤치마크

4w 2.5x8w 3.6x20w 5.0x28w 5.3x|선형 확장
CPU Intel Core i7-14700 (Raptor Lake) | Cores 20C / 28T (8P + 12E) | Boost P 5.4GHz · E 4.0GHz | Cache L3 33MB | RAM 64GB | Build MSVC C++23 Release
5.3x
28워커 기준 Per-core / Shared
7.65M
Per-core Peak (8w, P-core 최적)
2.34M
Shared Peak (4w, 이후 하락)
0
Locks / Contention Points

Throughput Scaling — 3-Model Comparison

Per-core / Shared Ratio by Worker Count

Raw Benchmark Data

Workers Per-core (msg/s) Shared (msg/s) Lock-Free (msg/s) Per-core / Shared

Architecture Analysis

Per-core가 고코어에서 압도적인 이유

  • 각 워커가 독립된 io_context를 소유 — 워커 간 공유 자원이 전혀 없음
  • Lock-free가 아니라 Lock-없음 — 뮤텍스 자체가 존재하지 않으므로 경합 비용 = 0
  • 각 코어의 L1/L2 캐시가 독점적으로 활용됨 — false sharing 원천 차단
  • 8워커(P-core 수)에서 7.65M msg/s 피크 도달 — 1워커 대비 3.87배로 거의 이상적인 선형 확장
8워커 이후 완만한 하락의 원인: i7-14700은 P-core 8개 + E-core 12개의 하이브리드 구조다. 8워커까지는 고성능 P-core에 1:1 매핑되어 이상적 확장을 보인다. 9~20워커부터 E-core가 투입되는데, E-core는 P-core 대비 처리 능력이 낮아 워커당 평균 처리량이 소폭 하락한다. 그럼에도 28워커에서 5.98M msg/s를 유지하며, Shared 대비 5.3배 격차를 만든다.

Shared가 고코어에서 역행하는 이유

  • 모든 워커가 동일 io_context의 run()을 호출 — 내부 큐가 단일 뮤텍스로 보호됨
  • 워커 4개까지는 경합이 제한적이어서 2.34M까지 상승
  • 8워커부터 lock 경합이 지배적이 되면서 처리량이 하락 (2.10M)
  • 28워커에서는 경합 오버헤드가 병렬 이득을 완전히 상쇄 — 1.13M으로 1워커(2.04M)의 절반 수준

Lock-Free가 Shared와 다르지 않은 이유

  • Lock-Free 모델은 세션 관리에서 뮤텍스를 CAS(Compare-And-Swap)로 대체
  • 그러나 진짜 병목인 io_context 내부 큐 뮤텍스는 Boost.Asio 내부에 있어 변경 불가
  • 4워커까지 Shared와 거의 동일 (2.33M vs 2.34M) — 세션 레벨 경합이 아직 부차적
  • 8워커 이후 Shared보다 더 나빠짐 (8w: 1.61M vs 2.10M) — CAS 실패 재시도 비용이 뮤텍스 대기보다 비효율적
  • 28워커에서 0.94M으로 3개 모델 중 최저 — 고경합 환경에서 CAS spinning은 역효과

v0.5.10 (4C) → v0.6.1 (20C) 비교

  • v0.5.10 (i5-9300H, 4C/8T): 최대 배율 2.1x (4워커) — 물리 코어 한계로 격차 제한
  • v0.6.1 (i7-14700, 20C/28T): 최대 배율 5.3x (28워커) — 코어 증가에 비례하여 격차 확대
  • 핵심: Per-core 모델은 코어가 늘어도 선형 확장하지만, Shared 모델은 코어가 늘수록 오히려 악화
  • 프로덕션 서버(64C+)에서는 배율이 더욱 극대화될 것으로 예상

결론: 코어가 많을수록 Per-core의 우위는 기하급수적으로 확대된다

이 벤치마크의 핵심 교훈은 명확하다: lock 최적화의 한계. Shared 모델은 뮤텍스 샤딩(v0.5.10)과 Lock-Free CAS(v0.6.1) 두 가지 최적화를 적용했지만, 그 아래에 있는 io_context 내부 큐의 단일 뮤텍스가 진짜 병목이었다. 아무리 상위 레벨의 lock을 최적화해도 하위 레벨에 공유 뮤텍스가 남아있으면 Amdahl의 법칙에 의해 확장성은 제한된다.


Per-core 아키텍처는 이 문제를 근본적으로 해결한다. 각 워커가 자신만의 io_context를 소유하므로 큐 경합 자체가 발생하지 않는다. 4코어 환경에서 2.1배였던 격차는 20코어에서 5.3배로 확대되었으며, 이는 코어 수가 증가할수록 격차가 발산함을 의미한다. 이것이 Apex Pipeline이 shared-nothing 아키텍처를 채택한 근본적인 이유다.