문제

우리는 많은 수의 큰 문자열 연결을 수행하는 몇 가지 작업이 있으며 최근에는 메모리 밖의 예외가 발생했습니다. 불행히도, 코드를 디버깅하는 것은 고객 사이트에서 발생하기 때문에 옵션이 아닙니다.

따라서 코드의 점검을 살펴보기 전에 큰 문자열에 대한 StringBuilder의 RAM 소비 특성은 무엇입니까?

특히 표준 문자열 유형과 비교할 때. 줄의 크기는 10MB 이상이며 약 20MB의 문제가 발생하는 것 같습니다.

노트: 이것은 속도가 아니라 RAM에 관한 것입니다.

도움이 되었습니까?

해결책

다음은 좋은 연구입니다 문자열 연결 대 메모리 할당.

연결을 피할 수 있다면 그렇게하십시오!

이것은 당신이 연결을 할 필요가 없지만 소스 코드가 멋지게 보이기를 원한다면, 첫 번째 방법을 사용하십시오. 마치 단일 문자열 인 것처럼 최적화됩니다.

+= 연결을 사용하지 마십시오. 현장 뒤에서 너무 많은 변화가 일어나고 있으며, 처음에는 내 코드에서 분명하지 않습니다. 오히려 string.concat ()를 과부하 (2 문자열, 3 문자열, 문자열 배열)와 함께 명시 적으로 사용하는 것이 좋습니다. 이것은 코드가 놀라움없이 무엇을하는지 명확하게 보여 주면서 효율성을 확인할 수있게합니다.

StringBuilder의 대상 크기를 추정하십시오.

필요한 크기를 더 정확하게 추정 할수록 StringBuilder가 내부 버퍼를 늘리기 위해 생성 해야하는 임시 문자열이 적습니다.

성능이 문제 일 때 어떤 형식 () 메소드를 사용하지 마십시오.

너무 많은 오버 헤드가 형식을 구문 분석하는 데 관여합니다. 사용중인 모든 것을 {x} 대체 할 때 조각으로 배열을 구성 할 수 있습니다. 형식 ()은 가독성에 적합하지만 응용 프로그램에서 가능한 모든 성능을 압박 할 때 가야 할 사항 중 하나입니다.

다른 팁

StringBuilder가 공간이 부족할 때마다 원래 버퍼의 두 배 크기의 새로운 버퍼를 재 할당하고 기존 문자를 복사하며 이전 버퍼가 gc'd를 얻을 수 있습니다. 2x가 할당 할 수있는 메모리보다 클 정도로 충분히 사용하고 있습니다 (x라고 함). 문자열의 최대 길이를 결정하고 StringBuilder의 생성자에게 전달하여 Prealloce를 할 수 있으며, 두 배의 재 할당의 자비가 아닙니다.

Ropes 데이터 구조에 관심이있을 수 있습니다. 이 기사 : 로프 : 이론과 연습 그들의 장점을 설명합니다. .NET에 대한 구현이있을 수 있습니다.

업데이트, 주석에 답하기 위해] 메모리를 적게 사용합니까? 검색 메모리 이 기사에서는 몇 가지 힌트를 찾을 수 있습니다.
기본적으로, 구조 오버 헤드에도 불구하고 필요할 때 메모리를 추가하기 때문에 그렇습니다. StringBuilder는 오래된 버퍼를 소진 할 때 훨씬 더 큰 버퍼를 할당해야하며 (이미 빈 메모리를 낭비 할 수 있음) 오래된 메모리를 삭제해야합니다 (쓰레기 수집이지만 여전히 많은 메모리를 사용할 수 있음).

.NET에 대한 구현을 찾지 못했지만 적어도 C ++ 구현이 있습니다 (SGI의 STL : http://www.sgi.com/tech/stl/rope.html). 이 구현을 활용할 수 있습니다. 참고 메모리 성능에 대한 작업이 있습니다.

로프는 모든 문제에 대한 치료법이 아닙니다. 유용성은 큰 문자열을 만드는 방법과 사용 방법에 따라 크게 달라집니다. 이 기사는 장점과 단점을 지적합니다.

StrigBuilder는 문자열을 연결하여 발생하는 메모리 문제에 대한 완벽한 솔루션입니다.

특정 질문에 답하기 위해 StringBuilder는 문자열의 길이가 현재 합의 된 StringBuilder 버퍼의 길이와 동일한 일반 문자열과 비교하여 일정한 크기의 오버 헤드를 가지고 있습니다. 버퍼는 잠재적으로 문자열 크기의 크기 일 수 있지만, 버퍼가 채워질 때까지 StringBuilder에 연결할 때 더 이상 메모리 할당이 이루어지지 않으므로 실제로 훌륭한 솔루션입니다.

문자열과 비교할 때 이것은 뛰어납니다.

string output = "Test";
output += ", printed on " + datePrinted.ToString();
output += ", verified by " + verificationName;
output += ", number lines: " + numberLines.ToString();

이 코드에는 코드에 리터럴로 저장된 4 개의 문자열이 있으며, 2 개는 메서드에서 생성되고 변수에서 1 개는 더 길고 길어지는 6 개의 개별 중간 문자열을 사용합니다. 이 패턴이 계속되면 GC가 차별을 시작할 때까지 메모리 사용량을 지수 속도로 증가시킵니다.

String Builder의 정확한 메모리 패턴에 대해 모르지만 공통 문자열은 옵션이 아닙니다.

공통 문자열을 사용하면 모든 연결은 또 다른 몇 개의 문자열 객체를 생성하고 메모리 소비가 급등하여 쓰레기 수집기가 너무 자주 호출됩니다.

string a = "a";

//creates object with a

a += "b"

/creates object with b, creates object with ab, assings object with ab to "a" pointer
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top