2013-07-01 2 views
2

정수 문자열에 하나의 문자열 또는 단일 char을 추가 할 때 성능에 영향이 있는지 궁금했습니다. (.NET 4) 당신이 루프를 언급해야문자열과 문자를 조합하는 성능

static class Program 
{ 
    const string STR = "string "; 

    static void Main() 
    { 
     var arr = new string[99999999]; 

     Stopwatch timer = new Stopwatch(); 

     Console.ReadLine(); 

     timer.Start(); 

     //for (uint i = 0; i < 99999999; i++) 
     //{ 
     // arr[i] = STR + 'C'; 
     //} 

     for (uint i = 0; i < 99999999; i++) 
     { 
      arr[i] = STR + "C"; 
     } 

     timer.Stop(); 

     Console.WriteLine(timer.ElapsedMilliseconds); 

     Console.ReadLine(); 
    } 
} 

:

그래서 나는 작은 콘솔 응용 프로그램을 썼다.

따라서 STR + "C"에는 약 1300 밀리 초가 걸립니다.

STR + 'C'에 대해서는 아직 결과를 확인할 수 없습니다. 너무 오래 걸리고 내 컴퓨터를 꽤 괴롭히는 것 같습니다.

내 질문은. 이 성능 영향은 어떻게 가능합니까? 실용적인 용도로는 99999999 값의 배열이 매우 자주 발생하지 않을 것이지만 여전히 큰 차이가 있습니다. 사전에

감사합니다!

답변

6

이것은 실제로 실제로 설명하기 쉽습니다. C# 컴파일러가 상수 폴딩을 문자열 식에서 수행한다는 사실을 발견했습니다.

STRconst으로 선언 했으므로 해당 참조가 리터럴 문자열 "string "으로 바뀌 었습니다. 그런 다음 컴파일러에서 "string " + "C"을 만나면 해당 표현식을 "string C"으로 바꿉니다. 따라서 실제로 끝나는 루프는 문자열을 배열의 다른 위치에 할당하는 데 모든 시간을 소비합니다.

반대로, char 연결은 실제로 (새로운 string 객체의 할당 포함) 연결뿐만 아니라 배열 할당을 모두 기다릴 필요가 있도록 하지는, 그런 식으로 최적화되어 있습니다. 또한 루프는 톤의 쓰레기를 생성하므로 수집기도 기다리고 있습니다. 당신이 공정하게이 작업을 비교하려면

, 나는 두 가지 일을 할 것입니다 :

  1. 변경합니다 STR의 선언을 static readonly 대신 const에.
  2. 실제로 반복 실행 횟수를 줄이면 전체 런아웃을 실제로 얻을 수 있습니다.
+0

대단히 감사합니다, 대단한 답변입니다! 상수가없는 'STR +'C ''는 문자를 추가하는 것보다 거의 두 배 빠릅니다. 그래서 지금은 단일 chararacter 문자열을 사용합니다. 다시 한 번 감사드립니다! – Andy

+0

@Andy 기꺼이 도와 드리겠습니다. 'char'를'string'으로 먼저 변환하지 않고'string'을 직접 연결할 수 있기 때문에 여러분의 관찰은 의미가 있습니다. – dlev

+0

@Andy Tigran의 대답과 결합하면 의미가 있습니다 :'+'연산자는 C# 컴파일러로 대체되어'String.Concat'을 호출합니다. 문자열과 함께 사용하면 문자열 매개 변수를 허용하는 오버로드를 직접 호출 할 수 있습니다. char과 함께 사용하면 char을 box하고 Object 매개 변수를 받아들이는 overload를 호출해야합니다. boxing 및 unboxing 작업은 상대적으로 비용이 많이 듭니다. 그러나 이것이 최고점에있는 마이크로 최적화라고주의하십시오! –

4

이런 간단한 프로그램 :

var val = "hello ";  
val += 'r'; 

우리 대신 string 경우 생성 IL

IL_0001: ldstr  "hello " 
IL_0006: stloc.0  // val 
IL_0007: ldloc.0  // val 
IL_0008: ldc.i4.s 72 
IL_000A: box   System.Char 
IL_000F: call  System.String.Concat 
IL_0014: stloc.0  // val 
IL_0015: ldloc.0  // val 

에서 볼 수 objectchar 값의 복싱을 실행한다 않음 없다 권투 관련, 그래서 그것은 significaly 빠릅니다.

그럼 왜 복싱이 실행됩니까? 두 개의 인수 (string)에 System.String.Concat(String,String) (즉, binary + 연산자 호출의 결과 임)을 호출하기 때문에 String.Concat(object,object)의 오버로드를 호출하므로 char의 값은 해당 메소드 호출에 전달 될 수 있도록 박스로 표시됩니다.

+1

설명하는 것을 잊었습니다. 이유는 무엇입니까? * 문자는 박스로 묶이지 만 문자열은 그렇지 않습니다. –

+0

@CodyGray : 내 게시물을 편집했습니다. – Tigran

관련 문제