디버그 대 릴리스 성능


132

다음 단락을 만났습니다.

“Visual Studio에서 코드를 컴파일 할 때 IDE의 디버그 및 릴리스 설정은 성능과 거의 차이가 없습니다. 생성 된 코드는 거의 같습니다. C # 컴파일러는 실제로 최적화를 수행하지 않습니다. C # 컴파일러는 IL을 뱉어 내고 런타임에 모든 최적화를 수행하는 JITer입니다. JITer에는 디버그 / 릴리스 모드가 있으며 성능에 큰 차이가 있습니다. 하지만 프로젝트의 디버그 또는 릴리스 구성을 실행하든 디버거가 연결되어 있는지를 결정하는 것은 아닙니다.”

소스는 여기에 있고 팟 캐스트는 여기에 있습니다 .

누군가 이것을 실제로 증명할 수있는 Microsoft 기사로 안내 할 수 있습니까?

인터넷 검색 " C # 디버그와 릴리스 성능 "은 대부분 " 디버그에 많은 성능 히트가 발생했습니다 ", " 릴리스가 최적화되었습니다 "및 " 디버그를 프로덕션에 배포하지 않음 "이라는 결과를 반환합니다 .



Win7-x86의 .Net4를 사용하면 메인 루프에 asserts / etc가없는 디버그보다 릴리스에서 거의 2 배 더 빠르게 실행되는 CPU 제한 프로그램이 있습니다.
Bengie

또한 메모리 사용에 관심이 있다면 큰 차이가있을 수 있습니다. 디버그 모드로 컴파일 된 다중 스레드 Windows 서비스가 스레드 당 700MB를 사용하고 릴리스 빌드의 스레드 당 50MB를 사용하는 경우를 보았습니다. 일반적인 사용 조건에서 디버그 빌드에 메모리가 빨리 부족합니다.
o. nate

@Bengie-디버거를 릴리스 빌드에 연결해도 여전히 2 배 빠르게 실행되는지 확인 했습니까? 위의 인용문은 JIT 최적화가 디버거의 연결 여부에 영향을받는다고 말합니다.
ToolmakerSteve

답변:


99

부분적으로 사실입니다. 디버그 모드에서 컴파일러는 모든 변수에 대해 디버그 기호를 생성하고 코드를있는 그대로 컴파일합니다. 릴리스 모드에서 일부 최적화가 포함됩니다.

  • 사용하지 않는 변수는 전혀 컴파일되지 않습니다
  • 변하지 않는 것으로 판명 된 경우 일부 루프 변수는 컴파일러에 의해 루프에서 제거됩니다.
  • #debug 지시문에 작성된 코드는 포함되지 않습니다.

나머지는 JIT에 달려 있습니다.

최적화의 전체 목록 에 여기 의 호의 에릭 Lippert의를 .


10
그리고 Debug.Asserts를 잊지 마십시오! DEBUG 빌드에서 실패하면 스레드가 중지되고 메시지 상자가 나타납니다. 릴리스에서는 전혀 컴파일되지 않습니다. 이것은 [ConditionalAttribute]가있는 모든 메소드에 적용됩니다.
Ivan Zlatanov

13
C # 컴파일러는 테일 호출 최적화를 수행하지 않습니다. 지터가합니다. 최적화 스위치가 켜져있을 때 C # 컴파일러의 정확한 목록을 보려면 blogs.msdn.com/ericlippert/archive/2009/06/11/…
Eric Lippert

63

성능 문제에 대해 "증명"하는 기사는 없습니다. 변경으로 인한 성능 영향에 대한 주장을 증명하는 방법은 현실적으로 제어되는 조건에서 두 가지 방법으로 모두 테스트하고 테스트하는 것입니다.

성능에 대한 질문을하고 있으므로 성능에 대해 분명히 신경을 씁니다. 퍼포먼스에 관심이 있다면, 올바른 목표는 퍼포먼스 목표를 설정하고 그 목표에 대한 진행 상황을 추적하는 테스트 스위트를 작성하는 것입니다. 이러한 테스트 스위트가 있으면 "디버그 빌드가 느리다"와 같은 문장의 진실 또는 허위를 스스로 테스트하기 위해 쉽게 사용할 수 있습니다.

또한 의미있는 결과를 얻을 수 있습니다. "느리게"는 1 마이크로 초 느리거나 20 분 느리게 명확하지 않기 때문에 의미가 없습니다. "현실적인 조건에서 10 % 느리게"가 더 의미가 있습니다.

질문에 대한 답변을 제공하는 장치를 구축하는 데이 질문을 온라인으로 조사하는 데 소요 된 시간을 보내십시오. 그렇게하면 훨씬 정확한 결과를 얻을 수 있습니다. 온라인에서 읽은 내용 발생할 수있는 일 에 대한 추측 일뿐 입니다. 프로그램이 어떻게 작동하는지에 대한 다른 사람들의 추측이 아니라 자신이 수집 한 사실 때문입니다.


2
성능에 신경을 쓸 수는 있지만 여전히 "디버그"를 사용하고 싶다고 생각합니다. 예를 들어, 대부분의 시간이 종속성을 기다리는 경우 디버그 모드로 빌드하면 큰 차이를 만들지 않을 것이라고 생각하지만 스택 추적에서 줄 번호를 얻는 이점이 추가되어 버그를 더 빨리 수정하고 만들 수 있습니다. 더 행복한 사용자. 요점은 장단점을 고려해야하며 일반적인 "디버그에서 실행하는 속도는 느리지 만 CPU에 제한이있는 경우에만"문으로 결정에 도움이됩니다.
Josh Mouch

11

성능에 대해서는 언급 할 수 없지만 "제품에 디버그를 배포하지 마십시오"라는 조언은 여전히 ​​큰 제품에서 디버그 코드가 상당히 다른 기능을 수행하기 때문에 여전히 유효합니다. 하나는 디버그 스위치를 활성화하고 다른 하나는 프로덕션 코드에 속하지 않는 여분의 중복성 검사 및 디버그 출력이있을 수 있습니다.


나는 그 문제에 대해 당신에게 동의하지만, 이것은 주요 질문에 답하지 않습니다
sagie

5
@ sagie : 예, 나는 그것을 알고 있지만 요점은 여전히 ​​가치가 있다고 생각했습니다.
Konrad Rudolph

6

에서 MSDN의 사회

잘 문서화되어 있지 않습니다. 여기 내가 아는 것이 있습니다. 컴파일러는 System.Diagnostics.DebuggableAttribute의 인스턴스를 생성합니다. 디버그 버전에서 IsJitOptimizerEnabled 속성은 True이고 릴리스 버전에서는 False입니다. ildasm.exe를 사용하여 어셈블리 매니페스트에서이 특성을 볼 수 있습니다.

JIT 컴파일러는이 속성을 사용하여 디버깅을 어렵게하는 최적화를 비활성화합니다. 루프 불변의 호이 스팅처럼 코드를 이동시키는 것. 선택된 경우 성능에 큰 차이를 만들 수 있습니다. 그러나 보통은 아닙니다.

중단 점을 실행 주소에 매핑하는 것은 디버거의 작업입니다. JIT 컴파일러가 생성 한 .pdb 파일 및 정보를 사용하여 코드 주소에 대한 IL 명령어 명령을 제공합니다. 자체 디버거를 작성하려면 ICorDebugCode :: GetILToNativeMapping ()을 사용합니다.

JIT 컴파일러 최적화가 사용 불가능하므로 기본적으로 디버그 배치가 느려집니다.


3

당신이 읽는 것은 매우 유효합니다. 디버그 코드 (#IF DEBUG 또는 [Conditional ( "DEBUG")]), 최소 디버그 심볼 로딩을 포함하지 않고 JIT 최적화로 인해 릴리스가 일반적으로 더 늦어지고 종종로드 시간을 단축시키는 작은 어셈블리가 고려되지 않습니다. 더 광범위한 PDB 및로드 된 기호로 인해 VS에서 코드를 실행할 때 성능 차이가 더 분명하지만 독립적으로 실행하면 성능 차이가 덜 분명해질 수 있습니다. 특정 코드는 다른 코드보다 더 잘 최적화되며 다른 언어와 마찬가지로 동일한 최적화 휴리스틱을 사용합니다.

Scott은 인라인 분석법 최적화에 대해 잘 설명하고 있습니다.

디버그 및 릴리스 설정에 대해 ASP.NET 환경에서 다른 이유를 간략하게 설명하는 이 문서 를 참조하십시오 .


3

성능과 디버거가 연결되어 있는지 여부와 관련하여 한 가지 유의해야 할 점은 놀라운 일입니다.

우리는 많은 빡빡한 루프를 포함하는 코드 조각을 가지고 있었고, 디버그하는 데 영원히 걸리는 것처럼 보였지만 자체적으로 잘 실행되었습니다. 다시 말해, 문제가 발생한 고객이나 고객은 없지만 디버깅 할 때 당밀처럼 작동하는 것 같습니다.

범인은 Debug.WriteLine타이트한 루프 중 하나였으며 수천 개의 로그 메시지를 뱉어 내고 디버그 세션에서 잠시 동안 빠져 나갔습니다. 디버거가 연결되어 이러한 출력을 수신하면 프로그램 속도가 느려지는 오버 헤드가있는 것 같습니다. 이 특정 코드의 경우 자체적으로 런타임이 0.2-0.3 초이고 디버거가 연결되었을 때 30 초 이상이었습니다.

그러나 간단한 해결책은 더 이상 필요하지 않은 디버그 메시지를 제거하십시오.


2

에서 MSDN 사이트 ...

릴리스 및 디버그 구성

프로젝트에서 작업하는 동안 일반적으로 디버그 구성을 사용하여 응용 프로그램을 빌드합니다.이 구성을 사용하면 디버거에서 변수 값을보고 실행을 제어 할 수 있기 때문입니다. 릴리스 구성에서 빌드를 작성하고 테스트하여 한 유형의 빌드에서만 나타나는 버그가 발생하지 않았는지 확인할 수 있습니다. .NET Framework 프로그래밍에서 이러한 버그는 매우 드물지만 발생할 수 있습니다.

최종 사용자에게 애플리케이션을 배포 할 준비가되면 릴리스 빌드를 작성하십시오. 릴리스 빌드는 훨씬 작으며 일반적으로 해당 디버그 구성보다 성능이 훨씬 우수합니다. 프로젝트 디자이너의 빌드 창 또는 빌드 도구 모음에서 빌드 구성을 설정할 수 있습니다. 자세한 내용은 빌드 구성을 참조하십시오.


1

대부분은 앱이 컴퓨팅 바운드인지 여부에 달려 있으며 Lasse의 예와 같이 항상 쉽게 알 수있는 것은 아닙니다. 내가하는 일에 대해 약간의 질문이 있으면 몇 번 일시 중지하고 스택을 검사하십시오. 실제로 필요하지 않은 추가 작업이 있으면 즉시 발견됩니다.


1

최근에 성능 문제가 발생했습니다. 제품 전체 목록이 너무 많은 시간이 소요되었습니다 (약 80 초). DB를 조정하고 쿼리를 개선했으며 아무런 차이가 없었습니다. 나는 TestProject를 만들기로 결정했고 같은 프로세스가 4 초 안에 실행되었다는 것을 알았습니다. 그런 다음 프로젝트가 디버그 모드에 있고 테스트 프로젝트가 릴리스 모드에 있음을 깨달았습니다. 기본 프로젝트를 릴리스 모드로 전환했으며 제품 전체 목록이 4 초만에 모든 결과를 표시했습니다.

요약 : 디버그 정보는 디버깅 정보를 유지하기 때문에 실행 모드보다 훨씬 느립니다. 항상 Relase 모드로 배포해야합니다. .PDB 파일을 포함 시키면 여전히 디버깅 정보를 가질 수 있습니다. 이렇게하면 예를 들어 줄 번호로 오류를 기록 할 수 있습니다.


"실행 모드"란 "릴리스"를 의미합니까?
Ron Klein

그렇습니다. 릴리스에는 모든 디버그 오버 헤드가 없습니다.
Francisco Goldenstein

1

디버그 및 릴리스 모드에는 차이가 있습니다. Fuzzlyn 도구가 있습니다 : Roslyn을 사용하여 임의의 C # 프로그램을 생성하는 퍼저 입니다. 이 프로그램은 .NET 코어에서 실행되며 디버그 및 릴리스 모드로 컴파일 될 때 동일한 결과를 제공합니다.

이 도구를 사용하여 많은 버그를 발견하고보고했습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.