2011-12-07 3 views
4

:
코드 1 : 느린 코드 1 이상의통화 방법의 성능이 저하됩니까? 예를 들어

void Main() 
{ 
    Foo(); 
} 

void Foo() 
{ 
    Console.WriteLine("Some texts"); 
} 

않는 코드 2 실행 : 2

void Main() 
{ 
    Console.WriteLine("Some texts"); 
} 

코드? 우리는 릴리스를 빌드 할 때 나는 비록 JIT는 그럼 코드 2는 코드 1로 빨리 실행 코드 2 인라인 것입니다하지만 LinqPad로를 테스트 할 때 나는 IL 결과를 얻었다 :

코드 1 :

IL_0000: ldstr  "Some texts" 
IL_0005: call  System.Console.WriteLine 

코드 2 : 우리는 코드 2의 IL 결과가 푸()를 호출하기위한 몇 가지 추가 단계가 볼 수 있듯이

IL_0000: ldarg.0  
IL_0001: call  UserQuery.Foo 

Foo: 
IL_0000: ldstr  "Some texts" 
IL_0005: call  System.Console.WriteLine 
IL_000A: ret  

, 이것은 코드 1보다 느리게 그 코드 2 실행을 증명 하는가?

+0

디버그 또는 릴리스 모드에서 실행 중이십니까? – Tudor

+0

@ Tudor : [LinqPad] (http://www.linqpad.net/)에서 테스트했는데 어떤 모드가 실행되었는지 전혀 모른다. Visual Studio에서 IL 결과를 표시하는 방법이 있습니까? – JatSing

+9

두 마리 있습니다. 당신은 더 빠른 것을 알고 싶습니다. (1) 빠른 속도로 인터넷에서 임의의 낯선 사람들에게 물어 보거나, (2) 말을 서로 경주하여 어느 것이 승리하는지 확인합니까? –

답변

8

먼저 JITted 어셈블리 코드가 아닌 IL을 살펴 보겠습니다. 당신이 보여준 것이 아무것도 증명하지 못합니다. JITted 출력을보고 JITter가 코드를 인라인했는지 확인해야합니다. JITter는 플랫폼에서 플랫폼 (예 : x86 대 x64)과 프레임 워크의 버전과 프레임 워크의 버전이 다릅니다.

두 번째로 서면 버전 2는 버전 1보다 느리게 실행됩니다. "서면으로"라고 말하면 JITter가 버전 2에서 호출을 인라인하지 않았다고 가정합니다. 추가 호출은 몇 가지 기계 명령어를 추가합니다. 물론 몇 번 실행하면됩니다 (다시 말하면, "서면으로 말한 것을 잊지 마십시오!"). 그러나 성능의 차이가 의미심장 한 일은 아닙니다. 당신은 의미있는 성능 차이를보기 위해 수조조 내지 수조 반복 동안 가장 단단한 루프에서이를 수행해야 할 것입니다.

+1

마지막으로, JITer는 버전 2에서 호출을 인라인 할 것입니까? – JatSing

+3

정말로 알고 싶다면 두 버전을 컴파일하고 JITter를 통해 압축 한 다음 출력 된 어셈블리를 살펴보십시오. – jason

+1

두 개의 컴파일러가 관련되어 있습니다. 보시다시피, IL 코드를 생성하는 C# 컴파일러의 출력입니다. 프로그램을 실행하면이 IL 코드가 jitted됩니다. 즉, 두 번째 컴파일러 인 Just-In-Time 컴파일러가 마이크로 프로세서에 대한 기계 코드를 생성합니다. C# 컴파일러가 메서드를 인라이닝하지 않더라도 지터가 발생할 수 있습니다. –

1

매우 사소한 (읽기 :있을 수 있음) 것이므로 걱정할 필요가 없습니다.

0

컴파일러는 코드 (어셈블리 코드)에 대한 자신의 해석을 작성하므로 코드 예제는 CPU에서 동일한 처리가 수행됩니다. (릴리스 모드에서)

+0

C# 컴파일러는 어셈블리 코드를 생성하지 않으므로 여기서 JIT 컴파일러를 사용한다고 가정합니다. 또한 컴파일러는 여성이 될 수도 있습니다. p – Lukazoid

+0

아득히 C# 컴파일러가 여전히 어셈블리 코드를 생성한다는 것을 알고 있습니다. 하지만 당신은 컴파일러가 여성이라는 것이 옳을 수도 있습니다. 그래서 그녀는 나에게 결코 경고를하지 않으므로, 그녀는 이후에 불평을합니다. P – stackr

+0

@ 루카 조이 (그리고 스택 러) 아마도 두 사람은 여기에서 다른 것을 의미하기 위해 "어셈블리"를 사용하고있을 것입니다. C# 컴파일러는 IL을 포함하는 어셈블리를 만듭니다. JIT 컴파일러는 기계 코드를 작성합니다. 기계어 코드는 어셈블리 언어와의 긴밀한 연관성으로 인해 "어셈블리 코드"라고도합니다. – phoog

1

C# 컴파일러는 인라이닝을 수행하지 않으며 이는 IL 코드에서 볼 수 있습니다. 인라인은 런타임 중에 JIT 옵티 마이저가 수행하는 작업입니다 (함수를 인라인하면 프로그램을보다 효율적으로 만듭니다).

2

예 메서드 호출은 C# - 컴파일러 또는 jit 컴파일러에 의해 인라인되지 않으면 코드 실행 속도가 약간 느려집니다. 그러나 코드가 반복적으로 실행되고 백만 번 정도 실행되지 않으면 깨끗하고 이해할 수 있고 유지 보수가 가능한 코드를 만드는 데 집중해야합니다. 단일 문장의 실행 시간을 밀리 초 또는 마이크로 초 단위로 프로그래밍하는 것으로 시작했을 때. 오늘날 나노초 단위로 측정됩니다. 일반적으로 시간은 주로 I/O 작업에 낭비됩니다. 나쁜 알고리즘도 몇 번이나 비난받을 수 있습니다. 디자인이 깔끔하게 구조화 된 경우 처음부터 시간 최적화 된 코드와 비교할 때 성능이 좋지 않은 코드 부분을 더 나은 코드로 대체하는 것이 훨씬 쉬울 것입니다.

나는 최근에 그것을 경험했다. Visio에서 복잡한 그래픽을 C# 프로그램으로 제작해야했습니다. Visio 자동화가 매우 느린 것으로 나타났습니다. 그래픽을 만들려면 몇 분이 걸렸습니다. 다행스럽게도 모든 그래픽 구성 요소를 제품 중립 인터페이스를 통해 노출 된 그래픽 구성 요소에 넣었습니다. 인터페이스는 Visio 특정 항목을 포함하지 않았습니다.Visio 구성 요소를 새 SVG 구성 요소로 대체하는 것이 매우 쉽습니다. 새 SVG 구성 요소는 1 초 이내에 같은 작업을 수행했습니다. 또한 알고리즘이나 다른 프로그램에서 변경하지 않아도됩니다.

원인, 제 그래픽 래퍼 구성 요소가 더 많은 메서드 호출을 추가합니다. 또한 인터페이스를 통해 액세스 할 수 있기 때문에 전체 작업 속도가 더욱 빨라집니다. 그러나 결국이 인터페이스와 이러한 추가 메서드 호출을 통해 훨씬 빠른 솔루션을 구현할 수있었습니다. 기억하십시오 : 분 대 1 초 미만!

2

이 경우 마지막으로 구현 한 내용을 읽었을 때 예와 같이 인라인됩니다.

일반적으로 대답은 어쩌면 - 인라인 규칙에 대한 문서는 규범 적 문서가 아닌 블로그에 주로 포함되어 있습니다. 세부 사항이 버전간에 변경 될 수있을뿐만 아니라 거의 확실합니다. 실제로

:

당신이 성능 핫스팟은 다음을 시도하고 다시 프로파일, 수동 인라인 혜택을 누릴 수 있다고 의심되는 경우

. 적어도 특정 부분에 대한 코드를보십시오. 이론적으로

: 아직도

, 나는 작은 방법은 인라인 것을 알고 좋아, 모두 같은.

관련 문제