StringBuilder 사용이 중요하지 않거나 오버헤드가 되는 시점은 언제입니까?

StackOverflow https://stackoverflow.com/questions/550702

  •  23-08-2019
  •  | 
  •  

문제

최근에 나는 크고 작은 모든 문자열 연결에 StringBuilder를 사용하고 있음을 발견했습니다. 그러나 최근 성능 테스트에서는 동료의 문자열을 교체했습니다. stringout = string1 + "." 문자열 2 StringBuilder에 대한 스타일 연결(매번 새로워지는 StringBuilder와 함께 10000x + 루프에서 사용됨)은 사소한 연결에서 어떤 차이가 있는지 확인하기 위한 것입니다.

성능 테스트를 여러 번 실행하면서 연결이나 StringBuilder에 관계없이 변경 사항이 미미하게 높거나 낮았다는 것을 발견했습니다. 작은 연결).

StringBuilder 개체를 '새로 만들기'하면 어떤 시점에서 개체 사용의 이점이 무효화됩니까?

도움이 되었습니까?

해결책

내가 따르는 규칙은 -

컴파일 시간에 연결 수를 알 수없는 경우 StringBuilder를 사용하십시오.

따라서 귀하의 경우 각 StringBuilder는 몇 번만 추가 한 다음 폐기되었습니다. 그것은 실제로 같은 것과 같지 않습니다

string s = String.Empty;
for (int i = 0; i < 10000; ++i)
{
    s += "A";
}

StringBuilder를 사용하면 새로운 메모리를 지속적으로 할당하기 때문에 성능이 크게 향상됩니다.

다른 팁

내가 게시 한 다른 답변이 있다고 확신합니다. 내 기사에 대한 링크 그리고 그 요약이지만 여기서 우리는 다시 간다.

  • 확실히 사용하십시오 StringBuilder 사소한 루프를 동의 할 때, 특히 (컴파일 시간에) 루프를 통해 얼마나 많은 반복을 만들 수 있는지 모르는 경우. 예를 들어, 한 번에 문자 파일을 읽고 += 연산자를 사용하면서 문자열을 구축하는 것은 잠재적으로 성능 자살입니다.

  • 하나의 문서에 연결해야 할 모든 것을 지정할 수있을 때 연결 연산자를 확실히 사용하십시오. (연결할 것들이있는 경우 전화를 고려하십시오. String.Concat 명시 적으로 - 또는 String.Join 구분 기가 필요한 경우.)

  • 리터럴을 여러 개의 연결 비트로 부수는 것을 두려워하지 마십시오. 결과는 동일합니다. 예를 들어 성능에 해를 끼치 지 않고 긴 문자를 여러 줄로 나누어 가독성을 도울 수 있습니다.

  • 다음의 반복을 공급하는 것 외에 다른 것에 대한 중급 결과가 필요한 경우, StringBuilder 당신을 도와주지 않을 것입니다. 예를 들어, 이름과 성에서 전체 이름을 구축 한 다음 세 번째 정보 (별명, 아마도)를 추가하면 결국 사용하면 혜택을 누릴 수 있습니다. StringBuilder 다른 목적을 위해 (이름 + 성) 문자열이 필요하지 않은 경우 Person 물체).

  • 할 일이 몇 가지 있고 별도의 진술로 실제로하고 싶다면 실제로 어떤 방식 으로든 상관 없습니다. 어떤 방식으로 더 효율적인 지에 따라 관련된 문자열의 크기와 관련된 순서에 따라 달라집니다. 실제로 그 코드 조각이 성능 병목 현상, 프로파일 또는 벤치마킹이라고 생각한다면 두 가지 방법이 있습니다.

때로는 볼 가치가 있습니다 선적 서류 비치:

문자열 또는 StringBuilder 객체에 대한 연결 작업의 성능은 메모리 할당이 얼마나 자주 발생하는지에 따라 다릅니다. 문자열 연결 작업은 항상 메모리를 할당하는 반면 StringBuilder 연결 작업은 StringBuilder 객체 버퍼가 너무 작아서 새 데이터를 수용 할 수없는 경우 메모리 만 할당합니다. 결과적으로 고정 된 수의 문자열 객체가 연결된 경우 연결 작업에 문자열 클래스가 바람직합니다. 이 경우 개별 연결 작업은 컴파일러에 의해 단일 작업으로 결합 될 수도 있습니다. 임의의 수의 문자열이 연결된 경우, 문자열 구매체 물체는 연결 작업에 바람직하다. 예를 들어, 루프가 임의의 문자열의 사용자 입력 문자열을 연결하는 경우.

예에서는 출력 문자열 당 하나의 연결 만 있으므로 StringBuilder는 아무것도 얻지 못합니다. 추가하는 경우 StringBuilder를 사용해야합니다. 같은 문자열 여러 번, 예를 들어 :

stringOut = ...
for(...)
    stringOut += "."
    stringOut += string2

내 경험의 규칙은 간단합니다.

  1. 최종을 생성하는 단일 표현을 합리적으로 작성할 수 있다면 +.
  2. (크기 또는 변동성으로 인해) 할 수없는 경우 StringBuilder를 사용하십시오.

내 경험상 : 다음과 같은 표현.

"Id: " + item.id + " name: " + item.name

다음보다 훨씬 쉽게 작성하고 이해할 수 있습니다.

StringBuilder sb = new StringBuilder();
sb.append("Id: ").append(item.id);
sb.append(" name: ").append(item.name);

(문자열을 사용하여 sb 위의 표현식이 작성된 곳), 똑같이 잘 수행됩니다 (힌트 : 컴파일 된 코드를보고 이유를 확인하십시오!)

반면에, 시간이 지남에 따라 문자열을 축적 할 필요가있을 때 (프로그램이 실행될 때) 또는 공간 (코드의 다른 부분에서 나오는 값으로 구성)은 단일 라인 표현식으로 쓰는 것이 비현실적 인 방식으로 그런 다음 StringBuilder는 다음의 오버 헤드 (시간 및 메모리 체성)를 피합니다.

String s = somethingExpression;
...
s += someOtherExpression;
...
s += yetAnotherExpression;
...

에서 MSDN:

고정 된 수의 문자열 객체가 연결된 경우 [T] HE 문자열 클래스는 연결 작업에 바람직합니다. 이 경우 개별 연결 작업은 컴파일러에 의해 단일 작업으로 결합 될 수도 있습니다. 임의의 수의 문자열이 연결된 경우, 문자열 구매체 물체는 연결 작업에 바람직하다. 예를 들어, 루프가 임의의 문자열의 사용자 입력 문자열을 연결하는 경우.

대답은 "의존적"이라고 생각합니다. 소수의 반복 이상으로 루프 내부에서 연결하고 있다면 StringBuilder는 거의 항상 더 나은 성능을 제공하지만 확실히 알 수있는 유일한 방법은 실제로 프로필입니다.

이에 대한 흥미로운 기사가 ​​있습니다. 코딩 호러.Jeff는 듀얼 코어 3.5GHz Core 2 Duo에서 100,000번의 반복에 대해 다음과 같은 결과를 얻었습니다.

 Simple Concatenation    - 606 ms
 String.Format           - 665 ms
 string.Concat           - 587 ms
 String.Replace          - 979 ms
 StringBuilder           - 588 ms

에서 도트 네트 펄스:

StringBuilder를 언제 사용해야합니까?

StringBuilder는 전적으로 최적화이며 내부 구현 이외의 String에 대한 논리적 개선을 제공하지 않습니다. 즉, 고성능 애플리케이션 및 웹 사이트에서 올바르게 사용하는 것이 중요합니다.

때로는 간단한 문자열 concats와 함께 4 이하의 작은 반복을 사용해도 괜찮습니다. 그러나 가장자리의 경우 이것은 비참 할 수 있습니다. StringBuilder와 함께 에지 케이스를 계획하십시오.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top