**PGO(Profile-Guided Optimization, 프로필 기반 최적화)**는 애플리케이션의 실제 실행 데이터를 수집하여, 가장 빈번하게 호출되는 코드 경로를 집중적으로 최적화하는 기술입니다. .NET 환경에서는 크게 JIT 방식의 **동적 PGO(Dynamic PGO)**와 AOT 방식의 정적 PGO로 나뉩니다.

주요 특징과 차이점은 다음과 같습니다.

1. JIT 환경의 동적 PGO (Dynamic PGO)

JIT 방식의 가장 강력한 무기 중 하나는 애플리케이션이 실행되는 동안 실시간으로 최적화가 가능하다는 점입니다.

  • 작동 방식: 앱이 실행되면 런타임이 코드의 실행 패턴(어떤 메서드가 많이 쓰이는지 등)을 분석합니다. 이후 수집된 데이터를 바탕으로 JIT 컴파일러가 '뜨거운(Hot)' 코드 영역을 더 효율적인 기계어로 **다시 최적화하여 재생성(Re-jitting)**합니다.
  • 장점: 시간이 지날수록 앱의 성능이 향상됩니다. 장기 실행되는 서버 애플리케이션에서는 이 동적 PGO 덕분에 JIT 방식의 최고 처리량(Peak Throughput)이 Native AOT를 능가하는 경우가 많습니다.
  • 계층화 컴파일(Tiered Compilation): ReadyToRun(R2R)이나 초기 JIT 코드가 성능이 낮더라도, 동적 PGO를 포함한 계층화 컴파일을 통해 나중에 더 고성능의 코드로 교체됩니다.

2. Native AOT와 PGO의 한계

Native AOT는 빌드 시점에 모든 컴파일을 마치기 때문에, 실행 중의 정보를 활용하는 동적 PGO를 지원하기 어렵습니다.

  • 정적 최적화의 한계: Native AOT는 빌드 시점의 정적 분석 정보만 사용합니다. 이로 인해 스트레스 테스트나 대규모 워크로드(Stage2 앱 등)에서 최고 속도가 최적화된 JIT 버전보다 낮게 측정될 수 있습니다.
  • 정적 PGO (Static PGO): Native AOT에서 PGO를 적용하려면, 앱을 먼저 실행하여 프로파일링 정보를 수집한 뒤 그 데이터를 다시 컴파일러에 넣어 빌드하는 복잡한 정적 PGO 과정이 필요합니다.

3. PGO 유무에 따른 성능 비교

최적화 시점 애플리케이션 실행 중 (실시간) 애플리케이션 빌드 시점
최고 처리량 매우 높음 (장기 실행 시 유리) 일관되나 JIT 최적화보다는 낮을 수 있음
적응성 실행 패턴 변화에 따라 재최적화 가능 고정된 최적화 상태 유지

구분JIT (Dynamic PGO)Native AOT

4. PGO 성능 차이를 줄이는 설정

Native AOT는 동적 PGO의 부재를 보완하기 위해 <OptimizationPreference>Speed</OptimizationPreference> 설정을 제공합니다. 이 설정은 컴파일러에게 파일 크기보다는 실행 속도와 처리량(Throughput)에 최우선순위를 두도록 지시하여, AOT 환경에서도 최대한 높은 RPS(초당 요청 수)를 확보할 수 있게 합니다.


비유하자면: **동적 PGO(JIT)**는 손님의 입맛을 관찰하며 실시간으로 조리법을 바꾸는 셰프와 같습니다. 처음에는 시간이 걸리지만, 단골손님이 생기면 그 손님에게 완벽히 맞춘 최고의 요리를 내놓습니다. 반면 Native AOT미리 작성된 정교한 레시피대로 만든 포장 요리와 같습니다. 누가 오든 즉시 음식을 내놓을 수 있지만, 특정 손님의 세세한 취향(런타임 데이터)에 맞춰 즉석에서 맛을 더 끌어올리기는 어렵습니다.

Posted by gurupia
,