programing

디버그 빌드와 릴리스 빌드 간의 성능 차이

goodcopy 2023. 5. 28. 22:18
반응형

디버그 빌드와 릴리스 빌드 간의 성능 차이

일반적으로 프로그램에서 디버그릴리스 구성을 전환하는 데 어려움이 없었으며, 프로그램이 실제로 고객 사이트에 배포된 경우에도 디버그 구성을 선택했습니다.

수동으로 변경하지 않는 경우 이러한 구성의 유일한 차이점은 디버그에는 상수가 정의되어 있고 릴리스에는 최적화 코드가 체크되어 있다는 입니다.

그래서 제 질문은 사실 두 가지입니다.

  1. 이 두 구성 사이에 성능 차이가 많이 있습니까?여기에 성능에 큰 차이를 일으킬 특정 유형의 코드가 있습니까, 아니면 실제로 그렇게 중요하지 않습니까?

  2. 릴리스 구성에서 실패할 수 있는 디버그 구성에서 정상적으로 실행되는 코드 유형이 있는지, 아니면 디버그 구성에서 테스트되고 정상적으로 작동하는 코드도 릴리스 구성에서 정상적으로 작동하는지 확인할 수 있습니까?

C# 컴파일러 자체는 릴리스 빌드에서 방출된 IL을 크게 변경하지 않습니다.주목할 점은 더 이상 곱슬곱슬한 대괄호에 중단점을 설정할 수 있는 NOPop 코드를 방출하지 않는다는 것입니다.가장 큰 것은 JIT 컴파일러에 내장된 옵티마이저입니다.다음과 같은 최적화 작업을 수행합니다.

  • 메소드 라이닝.메소드 호출은 메소드 코드를 주입하는 것으로 대체됩니다.이것은 큰 것입니다. 이것은 부동산 접근자들을 본질적으로 무료로 만듭니다.

  • CPU 레지스터 할당.로컬 변수와 메서드 인수는 스택 프레임에 다시 저장되지 않고 CPU 레지스터에 저장된 상태를 유지할 수 있습니다.이것은 최적화된 코드를 디버깅하는 것을 어렵게 만드는 것으로 유명한 큰 것입니다.그리고 휘발성 키워드에 의미를 부여하는 것.

  • 배열 인덱스 검사가 제거되었습니다.어레이 작업 시 중요한 최적화 기능(모든 .NET 컬렉션 클래스는 내부적으로 어레이를 사용함).JIT 컴파일러가 루프가 배열을 절대로 경계 밖으로 인덱싱하지 않는지 확인할 수 있으면 인덱스 검사가 제거됩니다.큰 거.

  • 루프를 풉니다.몸이 작은 루프는 코드를 몸 안에서 최대 4번 반복하고 루프를 적게 반복함으로써 개선됩니다.분기 비용을 절감하고 프로세서의 슈퍼 스칼라 실행 옵션을 개선합니다.

  • 데드 코드 제거.(false) { /.../ }이(가) 완전히 제거되는 경우와 같은 문장.이 문제는 반복적인 접힘 및 안감으로 인해 발생할 수 있습니다.다른 경우는 JIT 컴파일러가 코드에 가능한 부작용이 없다고 판단할 수 있는 경우입니다.이러한 최적화는 프로파일링 코드를 매우 까다롭게 만드는 이유입니다.

  • 코드 호이스트.루프의 영향을 받지 않는 루프 내부의 코드는 루프 밖으로 이동할 수 있습니다.C 컴파일러의 옵티마이저는 상승할 기회를 찾는 데 훨씬 더 많은 시간을 할애할 것입니다.그러나 데이터 흐름 분석이 필요하기 때문에 비용이 많이 드는 최적화이며 지터가 시간을 낼 수 없기 때문에 명백한 사례만 호이스트합니다..NET 프로그래머들이 더 나은 소스 코드를 작성하고 스스로 상승하도록 강요합니다.

  • 공통 하위 표현식 제거.x = y + 4; z = y + 4; z = x가 됨; dest[ix+1] = src[ix+1]와 같은 문장에서 매우 일반적임; 도우미 변수를 도입하지 않고 읽기 쉽도록 작성됨.가독성을 저하시킬 필요가 없습니다.

  • 지속적인 접힘.x = 1 + 2, x = 3이 됩니다. 이 간단한 예는 컴파일러에 의해 초기에 발견되지만 다른 최적화가 가능한 JIT 시간에 발생합니다.

  • 복사 전파.x = a; y = x; y = a; 이는 레지스터 할당자가 더 나은 결정을 내리는 데 도움이 됩니다.x86 지터에는 작업할 레지스터가 거의 없기 때문에 큰 문제입니다.올바른 항목을 선택하도록 하는 것은 수행하는 데 매우 중요합니다.

이러한 최적화는 앱의 디버그 빌드를 프로파일링하고 릴리스 빌드와 비교할 때 차이를 만들 수 있는 매우 중요한 최적화입니다.코드가 중요한 경로에 있을 때만 실제로 프로그램 성능에 영향을 미치는 코드의 5~10%가 중요합니다.JIT 옵티마이저는 무엇이 중요한지 미리 알 수 있을 만큼 똑똑하지 않습니다. 모든 코드에 대해 "11시로 전환" 다이얼만 적용할 수 있습니다.

프로그램 실행 시간에 대한 이러한 최적화의 효과적인 결과는 다른 곳에서 실행되는 코드의 영향을 받는 경우가 많습니다.파일 읽기, 데이터베이스 쿼리 실행 등JIT 옵티마이저가 하는 일을 완전히 보이지 않게 만드는 것.그래도 괜찮아요 :)

JIT 최적화기는 수백만 번 테스트를 거쳤기 때문에 상당히 신뢰할 수 있는 코드입니다.프로그램의 릴리스 빌드 버전에서 문제가 발생하는 경우는 매우 드문 경우입니다.하지만 그것은 일어납니다.x64와 x86 지터 모두 구조물에 문제가 있었습니다.x86 지터는 부동소수점 일관성에 문제가 있으며, 부동소수점 계산의 중간값이 메모리로 플러시될 때 잘리는 대신 80비트 정밀도로 FPU 레지스터에 유지될 때 미묘하게 다른 결과를 생성합니다.

  1. 예, 많은 성능 차이가 있으며 이러한 차이는 코드 전체에 적용됩니다.디버그는 성능 최적화와 릴리스 모드를 거의 수행하지 않습니다.

  2. DEBUG빌드와 될 수 .그 외에, 당신은 어떤 문제도 보지 말아야 합니다.

의 예DEBUG는 수는상입니다.Debug.Assert()이 속이있메서인 입니다.[Conditional("DEBUG)"]확정된이것은 또한 그것이 의존한다는 것을 의미합니다.DEBUG상수이며 이는 릴리스 빌드에 포함되지 않습니다.

이는 응용 프로그램의 특성에 따라 크게 달라집니다.응용 프로그램이 UI를 많이 사용하는 경우 최신 컴퓨터에 연결된 가장 느린 구성 요소가 사용자이기 때문에 차이를 느끼지 못할 수 있습니다.일부 UI 애니메이션을 사용하는 경우 DEBUG 빌드에서 실행할 때 눈에 띄는 지연이 있는지 테스트할 수 있습니다.

그러나 계산 부하가 높은 계산이 많은 경우 차이가 있음을 알 수 있습니다(계산의 특성에 따라 다르지만 @Pieter가 언급한 것처럼 40%까지 높을 수 있음).

이것은 기본적으로 디자인의 절충입니다.DEBUG 빌드로 릴리스하는 경우 사용자에게 문제가 발생하면 더 의미 있는 추적을 받을 수 있으며 훨씬 더 유연한 진단을 수행할 수 있습니다.DEBUG 빌드로 릴리스하면 옵티마이저가 모호한 하이젠 버그를 생성하는 것을 방지할 수 있습니다.

  • 중간 크기 이상의 애플리케이션이 릴리스 빌드에서 훨씬 더 응답성이 높다는 것이 제 경험입니다.애플리케이션을 사용해 보고 어떤 느낌인지 확인해 보십시오.

  • 릴리스 빌드에서 문제가 될 수 있는 한 가지는 디버그 빌드 코드가 때때로 레이스 조건 및 기타 스레드 관련 버그를 억제할 수 있다는 것입니다.최적화된 코드를 사용하면 명령어 순서가 다시 지정될 수 있으며 실행 속도가 빨라지면 특정 인종 조건이 악화될 수 있습니다.

.NET 디버그 빌드를 운영 환경에 릴리스해서는 안 됩니다.편집 및 계속을 지원하는 추악한 코드가 포함되어 있거나 다른 정보를 알고 있는 사용자가 포함되어 있을 수 있습니다.제가 아는 한, 이것은 C#이 아닌 VB에서만 발생합니다(참고: 원래 게시물은 C# 태그가 지정됨). 하지만 Microsoft가 디버그 빌드로 수행할 수 있다고 생각하는 작업에 대해 일시 중지할 이유를 제공해야 합니다.실제로 .NET 4.0 이전 버전에서는 편집 및 계속을 지원하기 위해 구성하는 이벤트가 있는 개체의 인스턴스 수에 비례하여 VB 코드가 메모리를 누출합니다.(https://connect.microsoft.com/VisualStudio/feedback/details/481671/vb-classes-with-events-are-not-garbage-collected-when-debugging, 에 따라 수정된 것으로 보고되지만 생성된 코드는 보기에 좋지 않습니다.WeakReference객체를 고정한 상태에서 정적 목록에 추가) 프로덕션 환경에서 이러한 디버깅 지원을 원하지 않습니다!

저는 그렇게 말할 거예요.

  1. 구현에 따라 크게 달라집니다.보통, 그 차이는 그렇게 크지 않습니다.저는 많은 측정을 했고 종종 차이를 볼 수 없었습니다.관리되지 않는 코드, 많은 대용량 어레이 등을 사용하는 경우 성능 차이는 약간 더 크지만 C++와 같은 다른 환경은 아닙니다.

  2. 일반적으로 릴리스 코드에서는 더 적은 오류(높은 허용오차)가 표시되므로 스위치가 잘 작동합니다.

제 경험상, 릴리스 모드에서 나온 최악의 것은 모호한 "릴리스 버그"입니다.IL(중간 언어)은 릴리스 모드에서 최적화되므로 디버그 모드에서는 나타나지 않는 버그가 있을 수 있습니다.이 문제를 다루는 다른 SO 질문이 있습니다.릴리스 버전의 버그가 디버그 모드에 없는 일반적인 이유

단순한 콘솔 앱이 디버그 모드에서는 완벽하게 실행되지만 정확하게 동일한 입력이 주어지면 릴리스 모드에서는 오류가 발생하는 경우가 한두 번 있었습니다.이러한 버그는 매우 디버깅하기 어렵습니다(반어적으로 릴리스 모드의 정의에 따라).

    **Debug Mode:**
    Developer use debug mode for debugging the web application on live/local server. Debug mode allow developers to break the execution of program using interrupt 3 and step through the code. Debug mode has below features:
   1) Less optimized code
   2) Some additional instructions are added to enable the developer to set a breakpoint on every source code line.
   3) More memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are not cached.
   5) It has big size, and runs slower.

    **Release Mode:**
    Developer use release mode for final deployment of source code on live server. Release mode dlls contain optimized code and it is for customers. Release mode has below features:
   1) More optimized code
   2) Some additional instructions are removed and developer can’t set a breakpoint on every source code line.
   3) Less memory is used by the source code at runtime.
   4) Scripts & images downloaded by webresource.axd are cached.
   5) It has small size, and runs fast.

제 대답이 매우 늦고 제 대답이 정확히 당신이 원하는 것이 아니라는 것을 알지만, 저는 확실하고 간단한 예를 들어 플레이하는 것이 좋을 것이라고 생각했습니다.어쨌든, 이 코드 조각은 디버그와 릴리스 엄청난 차이를 초래합니다.코드는 비주얼 스튜디오 2019의 C++로 작성되었습니다.코드는 다음과 같습니다.

#include <iostream>

using namespace std;

unsigned long long fibonacci(int n)
{
    return n < 2 ? n : (fibonacci(n - 1) + fibonacci(n - 2));
}

int main()
{
    int x = 47;

    cout << "Calculating..." << endl;
    cout << "fib(" << x << ") = " << fibonacci(x) << endl;
}

편집: 피보나치 시퀀스 계산 시 성능 차이

                       Debug        Release         
                C++ x86 C++ x64 C++ x86 C++ x64 C# Debug    C# Release
Time (mSeconds) 99384.9 27799.1 11066.0 11321.5 95233.7 24566.0
Time (Seconds)  99.4    27.8    11.1    11.3    95.2    24.6

언급URL : https://stackoverflow.com/questions/4043821/performance-differences-between-debug-and-release-builds

반응형