다음을 통해 공유


빌드 시간에 함수 인라인 처리 문제 해결

Build Insights 함수 뷰를 사용하여 C++ 프로젝트의 빌드 시간에 함수 인라인이 미치는 영향 문제를 해결합니다.

필수 조건

  • Visual Studio 2022 17.8 이상.
  • C++를 사용한 데스크톱 개발 워크로드 또는 C++를 사용한 게임 개발 워크로드를 설치하는 경우 C++ Build Insights는 기본적으로 사용하도록 설정됩니다.

C++ 워크로드를 사용한 데스크톱 개발이 선택된 Visual Studio 설치 관리자의 스크린샷.

설치된 구성 요소 목록이 표시됩니다. C++ Build Insights가 강조 표시되고 선택되어 있으면 설치된 것입니다.

C++를 사용한 게임 개발 워크로드가 선택된 Visual Studio 설치 관리자의 스크린샷.

설치된 구성 요소 목록이 표시됩니다. C++ Build Insights가 강조 표시되고 선택되어 있으면 설치된 것입니다.

개요

이제 Visual Studio에 통합된 Build Insights는 특히 AAA 게임과 같은 대규모 프로젝트의 경우 빌드 시간을 최적화하는 데 도움이 됩니다. Build Insights는 빌드 시간 동안 비용이 많이 드는 코드 생성을 진단하는 데 도움이 되는 함수 뷰와 같은 분석을 제공합니다. 각 함수에 대한 코드를 생성하는 데 걸리는 시간을 표시하고 __forceinline의 영향을 보여 줍니다.

__forceinline 지시문은 크기나 복잡성에 관계없이 함수를 인라인하도록 컴파일러에 지시합니다. 함수를 인라인하면 함수 호출에 따른 오버헤드가 줄어들어 런타임 성능이 개선될 수 있습니다. 단점은 이진 파일 크기가 증가하고 빌드 시간에 영향을 미칠 수 있다는 것입니다.

최적화된 빌드의 경우 코드 생성에 소요되는 시간이 총 빌드 시간에 크게 영향을 미칩니다. 일반적으로 C++ 함수 최적화는 빠르게 이루어집니다. 예외적인 경우, 일부 함수는 최적화 프로그램에 압력을 가하고 빌드 속도를 눈에 띄게 느리게 할 만큼 충분히 크고 복잡해질 수 있습니다.

이 문서에서는 Build Insights 함수 뷰를 사용하여 빌드에서 인라인 병목 현상을 찾는 방법을 알아봅니다.

빌드 옵션 설정

디버그 빌드는 최적화를 사용하지 않도록 설정하는 /Ob0 컴파일러 스위치를 사용하므로 __forceinline의 결과를 측정하려면 디버그 빌드는 인라인 __forceinline을 수행하지 않으므로 릴리스 빌드를 사용합니다. 릴리스x64용 빌드를 설정합니다.

  1. 솔루션 구성 드롭다운에서 릴리스를 선택합니다.
  2. 솔루션 플랫폼 드롭다운에서 x64를 선택합니다.

릴리스로 설정된 솔루션 구성 드롭다운과 x64로 설정된 솔루션 플랫폼의 스크린샷.

최적화 수준을 최대 최적화로 설정합니다.

  1. 솔루션 탐색기에서 프로젝트 이름을 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.

  2. 프로젝트 속성에서 C/C++>최적화로 이동합니다.

  3. 최적화 드롭다운을 최대 최적화(우선 속도)(/O2)로 설정합니다.

    프로젝트 속성 페이지 대화 상자의 스크린샷. 설정은 구성 속성 > C/C++ > 최적화에 열려 있습니다. 최적화 드롭다운은 최대 최적화(선호 속도)(/O2)로 설정됩니다.

  4. 확인 을 클릭하여 대화 상자를 닫습니다.

Build Insights 실행

선택한 프로젝트에서 이전 섹션에 설정된 릴리스 빌드 옵션을 사용하여 기본 메뉴 빌드>선택 시 Build Insights 실행>다시 빌드를 선택하여 Build Insights를 실행합니다. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 Build Insights 실행>다시 빌드를 선택할 수도 있습니다. 빌드 대신 다시 빌드를 선택하여 현재 더러워진 소수의 파일뿐만 아니라 전체 프로젝트의 빌드 시간을 측정합니다.

선택 시 Build Insights 실행 > 다시 빌드가 선택된 기본 메뉴의 스크린샷.

빌드가 완료되면 ETL(이벤트 추적 로그) 파일이 열립니다. Windows TEMP 환경 변수가 가리키는 폴더에 저장됩니다. 생성된 이름은 컬렉션 시간을 기준으로 합니다.

함수 뷰

ETL 파일 창에서 함수 탭을 선택합니다. 컴파일된 함수와 각 함수에 대한 코드를 생성하는 데 걸린 시간을 보여 줍니다. 함수에 대해 생성된 코드의 양이 무시할 수 있는 경우 빌드 이벤트 컬렉션 성능 저하를 방지하기 위해 목록에 표시되지 않습니다.

Build Insights 함수 뷰 파일의 스크린샷.

함수 이름 열에서 PerformPhysicsCalculations()가 강조 표시되고 불 아이콘으로 표시됩니다.::

시간 [초, %] 열은 WCTR(벽시계 책임 시간)에서 각 함수를 컴파일하는 데 걸린 시간을 보여 줍니다. 이 메트릭은 병렬 컴파일러 스레드 사용을 기반으로 함수 간에 벽시계 시간을 배포합니다. 예를 들어, 두 개의 서로 다른 스레드가 1초 내에 두 개의 서로 다른 함수를 동시에 컴파일하는 경우 각 함수의 WCTR은 0.5초로 기록됩니다. 이는 병렬 실행 중에 각각 소비되는 리소스를 고려하여 총 컴파일 시간에 대한 각 함수의 비례적인 점유율을 반영합니다. 따라서 WCTR은 여러 컴파일 작업이 동시에 발생하는 환경에서 각 함수가 전체 빌드 시간에 미치는 영향을 더 잘 측정할 수 있습니다.

Forceinline 크기 열은 해당 함수에 대해 생성된 명령 수를 대략적으로 보여 줍니다. 함수 이름 앞의 펼침 단추를 클릭하면 해당 함수에서 확장된 개별 인라인 함수를 확인하고 각 함수에 대해 대략 몇 개의 명령이 생성되었는지 확인할 수 있습니다.

시간 열을 클릭하면 목록을 정렬하여 컴파일하는 데 가장 많은 시간이 걸리는 함수를 확인할 수 있습니다. '불' 아이콘은 해당 함수를 생성하는 데 드는 비용이 높고 조사할 가치가 있음을 나타냅니다. __forceinline 함수를 과도하게 사용하면 컴파일 속도가 크게 느려질 수 있습니다.

필터 함수 상자를 사용하여 특정 함수를 검색할 수 있습니다. 함수의 코드 생성 시간이 너무 짧으면 함수 뷰에 표시되지 않습니다.

함수 인라인을 조정하여 빌드 시간 개선

이 예에서는 performPhysicsCalculations 함수가 컴파일하는 데 가장 많은 시간이 걸립니다.

Build Insights 함수 뷰의 스크린샷.

함수 이름 열에서 PerformPhysicsCalculations()가 강조 표시되고 불 아이콘으로 표시됩니다.

해당 함수 앞의 펼침 단추를 선택한 다음 Forceinline 크기 열을 가장 높은 열에서 가장 낮은 열 순으로 정렬하여 자세히 조사하면 문제의 가장 큰 원인을 파악할 수 있습니다.

확장된 함수가 포함된 Build Insights 함수 뷰의 스크린샷.

PerformPhysicsCalculations()가 확장되어 내부에 인라인된 긴 함수 목록이 표시됩니다. complexOperation(), recursiveHelper() 및 sin()과 같은 함수의 여러 인스턴스가 표시됩니다. Forceinline 크기 열은 complexOperation()이 315개 명령에서 가장 큰 인라인 함수임을 보여 줍니다. recursiveHelper()에는 119개의 명령이 있습니다. Sin()에는 75개의 명령이 있지만 다른 함수보다 더 많은 인스턴스가 있습니다.

문제를 일으키는 Vector2D<float>::complexOperation()Vector2D<float>::recursiveHelper()와 같은 몇 가지 더 큰 인라인 함수가 있습니다. 그러나 Vector2d<float>::sin(float), Vector2d<float>::cos(float), Vector2D<float>::power(float,int)Vector2D<float>::factorial(int)의 인스턴스가 더 많이 있습니다(여기에 모두 표시되지는 않음). 이를 합산하면 생성된 명령의 총 수가 생성된 몇 가지 더 큰 함수를 빠르게 초과합니다.

소스 코드에서 해당 함수를 살펴보면 실행 시간이 루프 내부에서 소비된다는 것을 알 수 있습니다. 예를 들어, factorial()에 대한 코드는 다음과 같습니다.

static __forceinline T factorial(int n)
{
    T result = 1;
    for (int i = 1; i <= n; ++i) {
        for (int j = 0; j < i; ++j) {
            result *= (i - j) / (T)(j + 1);
        }
    }
    return result;
}

이 함수를 호출하는 데 드는 전체 노력은 함수 자체의 노력에 비해 중요하지 않을 수 있습니다. 함수를 호출하는 데 걸리는 시간(스택에 인수 푸시, 함수로 점프, 반환 인수 팝핑 및 함수에서 반환)이 함수를 실행하는 데 걸리는 시간과 비슷할 때와 함수가 많이 호출될 때 함수를 인라인으로 만드는 것이 가장 좋습니다. 이 경우가 아니면 인라인으로 만들면 효과가 줄어들 수 있습니다. 빌드 시간에 도움이 되는지 확인하기 위해 __forceinline 지시문을 제거해 볼 수 있습니다. power, sin()cos()의 코드는 코드가 여러 번 실행되는 루프로 구성된다는 점에서 유사합니다. 해당 함수에서도 __forceinline 지시문을 제거해 볼 수 있습니다.

기본 메뉴에서 빌드>선택 시 Build Insights 실행>다시 빌드를 선택하여 Build Insights를 다시 실행합니다. 솔루션 탐색기에서 프로젝트를 마우스 오른쪽 단추로 클릭하고 Build Insights 실행>다시 빌드를 선택할 수도 있습니다. 이전과 마찬가지로 전체 프로젝트의 빌드 시간을 측정하기 위해 빌드 대신 다시 빌드를 선택합니다. 지금 당장은 문제를 발생시킬 수 있는 일부 파일은 제외합니다.

빌드 시간은 25.181초에서 13.376초로 증가하고 performPhysicsCalculations 함수는 계산할 빌드 시간에 충분히 기여하지 않기 때문에 더 이상 함수 뷰에 표시되지 않습니다.

2D 벡터 헤더 파일의 스크린샷.

함수 이름 열에서 PerformPhysicsCalculations()가 강조 표시되고 불 아이콘으로 표시됩니다.::

진단 세션 시간은 빌드를 수행하는 데 걸린 전체 시간과 Build Insights 데이터를 수집하는 데 드는 오버헤드를 합한 것입니다.

다음 단계는 애플리케이션의 성능이 변경으로 인해 부정적인 영향을 받는지 확인하기 위해 애플리케이션을 프로파일링하는 것입니다. 그렇다면 필요에 따라 선택적으로 __forceinline을 다시 추가할 수 있습니다.

함수 뷰에서 파일을 두 번 클릭하거나 마우스 오른쪽 단추로 클릭하거나 Enter 키를 눌러 해당 파일의 소스 코드를 엽니다.

함수 뷰에서 파일을 마우스 오른쪽 단추로 클릭하는 것을 보여 주는 스크린샷. 메뉴 옵션 원본 파일로 이동이 강조 표시됩니다.

  • ETL 파일을 보다 영구적인 위치에 파일>다른 이름으로 저장하여 빌드 시간을 기록할 수 있습니다. 그런 다음 이를 향후 빌드와 비교하여 변경 내용으로 인해 빌드 시간이 개선되는지 확인할 수 있습니다.
  • 실수로 Build Insights 창을 닫은 경우 임시 폴더에서 <dateandtime>.etl 파일을 찾아서 다시 엽니다. TEMP Windows 환경 변수는 임시 파일 폴더의 경로를 제공합니다.
  • WPA(Windows Performance Analyzer)를 사용하여 Build Insights 데이터를 자세히 살펴보려면 ETL 창 오른쪽 하단에 있는 WPA에서 열기 단추를 클릭합니다.
  • 열 순서를 변경하려면 열을 끕니다. 예를 들어, 시간 열을 첫 번째 열로 이동하는 것이 좋습니다. 열 머리글을 마우스 오른쪽 단추로 클릭하고 표시하지 않으려는 열을 선택 취소하여 열을 숨길 수 있습니다.
  • 함수 뷰에서는 관심 있는 함수를 찾을 수 있는 필터 상자를 제공합니다. 제공한 이름과 부분적으로 일치합니다.
  • 함수 뷰에서 표시하려는 내용을 해석하는 방법을 잊어버린 경우 탭를 마우스로 가리키면 뷰를 설명하는 도구 설명을 볼 수 있습니다. 함수 탭를 마우스로 가리키면 도구 설명에 "자식 노드가 강제 인라인된 함수인 함수에 대한 통계를 표시하는 뷰"라고 표시됩니다.

문제 해결

  • Build Insights 창이 표시되지 않으면 빌드 대신 다시 빌드를 수행합니다. 실제로 아무것도 빌드되지 않으면 Build Insights 창이 나타나지 않습니다. 마지막 빌드 이후 파일이 변경되지 않은 경우일 수 있습니다.
  • 함수 뷰에 함수가 표시되지 않으면 올바른 최적화 설정으로 빌드하지 않은 것일 수 있습니다. 빌드 옵션 설정에 설명된 대로 전체 최적화를 통해 릴리스를 빌드하고 있는지 확인합니다. 또한 함수의 코드 생성 시간이 너무 짧으면 목록에 나타나지 않습니다.

참고 항목

Insights 팁 및 요령 빌드
인라인 함수(C++)
더 빨라진 C++ 빌드, 간소화된 새로운 시간 메트릭
Visual Studio의 Build Insights 동영상 - Pure Virtual C++ 2023
빌드 시간에 헤더 파일이 미치는 영향 문제 해결
Visual Studio 2022 17.8의 Build Insights에 대한 함수 뷰
자습서: vcperf 및 Windows Performance Analyzer
C++ Build Insights를 사용하여 코드 생성 시간 개선