2016-12-21 3 views
1

일련의 파일을 루프로 작성하는 프로그램이 있습니다. 파일 이름은 메서드에 제공되는 개체의 매개 변수를 사용하여 구성됩니다.문자열 연결 속도 향상

public string CreateFilename(MyObject obj) 
{ 
    return "sometext-" + obj.Name + ".txt"; 
} 

이 일을 좀 더 성능이 좋은 방법이 있나요 :

개미 성능 프로파일 러는이 개 느리고 내가 왜 확실하지 않다라고? 이 방법은 수천 번 발생하며 입력 객체가 제어 할 수없고 정기적으로 변경되기 때문에이 방법을 사용하지 않는 좋은 방법을 알지 못합니다.

String.Concat("sometext-", obj.Name, ".txt") 

이 작업을 수행 할 빠른 방법은 없습니다 :

+1

'String.Format()'함수를 사용하여 벤치마킹 할 수 있습니다. 그러나 tbh, 연결 비용이 매우 높지는 않습니다. 이것은 불필요한 최적화라고 생각합니까? – Jite

+0

'obj'당 얼마나 자주 호출 되는가? –

+1

은'StringBuilder'를 사용합니다. 분명히'StringBuilder'는 한 번만 초기화 할 수있는 private 필드이어야합니다. 그러나 당신이 원하는만큼 그것을 사용하십시오. –

답변

8

컴파일러는 하나의 호출로 두 concats을 최적화합니다.

+0

정확히. 참조 소스 (https://referencesource.microsoft.com/#mscorlib/system/string.cs,e7f761c274d2036b –

+0

)를 참조하십시오. 나는 그것을 두려워했다. – joelc

2

대신 클래스 자체에서 파일 이름을 계산하면 개체를 수정할 때 성능이 저하되는 대신 훨씬 빠르게 실행됩니다. 파일 이름을 계산하는 것이 병목 현상이라면 나는 매우 걱정할 것이다. 파일에 쓰는 것은 이름이 떠오르는 것보다 느립니다.

아래 코드 샘플을 참조하십시오. (LINQPad 5에서) 최적화를 사용하여 벤치마킹 할 때 Test2는 Test1보다 약 15 배 빠릅니다. Test2는 작은 문자열 개체를 끊임없이 생성/삭제하지 않습니다.

void Main() 
{ 
    Test1(); 
    Test1(); 
    Test1(); 
    Test2(); 
    Test2(); 
    Test2(); 
} 

void Test1() 
{ 
    System.Diagnostics.Stopwatch sw = new Stopwatch(); 
    MyObject1 mo = new MyObject1 { Name = "MyName" }; 
    sw.Start(); 
    long x = 0; 
    for (int i = 0; i < 10000000; ++i) 
    { 

     x += CreateFileName(mo).Length; 
    } 
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations 
    sw.ElapsedMilliseconds.Dump("Test1"); 
} 

public string CreateFileName(MyObject1 obj) 
{ 
    return "sometext-" + obj.Name + ".txt"; 
} 

void Test2() 
{ 
    System.Diagnostics.Stopwatch sw = new Stopwatch(); 
    MyObject2 mo = new MyObject2 { Name = "MyName" }; 
    sw.Start(); 
    long x = 0; 
    for (int i = 0; i < 10000000; ++i) 
    { 
     x += mo.FileName.Length; 
    } 
    Console.WriteLine(x); //Sanity Check, prevent clever compiler optimizations 
    sw.ElapsedMilliseconds.Dump("Test2"); 
} 



public class MyObject1 
{ 
    public string Name; 
} 

public class MyObject2 
{ 
    public string FileName { get; private set;} 
    private string _name; 
    public string Name 
    { 
     get 
     { 
      return _name; 
     } 
     set 
     { 
      _name=value; 
      FileName = "sometext-" + _name + ".txt"; 
     } 
    } 
} 

는 또한 CreateFileName에 메모이 제이션을 추가 테스트,하지만 거의 Test1을 통해 성능을 개선하고, 해시 조회를 위해 추가 오버 헤드에 해당하는 단계를 수행하기 때문에 그것이 가능, Test2를을 이길 수 없었다.