C\#StringBuilder 메모리 조각 이 성능 에 미 치 는 영향
4912 단어 C#StringBuilder메모리 조각
연속 메모리 와 불 연속 메모리 의 성능 이 떨 어 지면 1600 배 에 이 를 수 있다.
배경
StringBuilder 를 사용 하 는 사용 자 는 대부분 StringBuilder 로 html/json 템 플 릿 을 연결 하고 동적 SQL 을 조립 하 는 등 정상 적 인 작업 을 하려 고 할 수 있 습 니 다.그러나 일부 특수 한 장면 에서-예 를 들 어 특정한 프로 그래 밍 언어 에 언어 서 비 스 를 쓰 거나 부 텍스트 편집 기 를 쓸 때 StringBuilder 는 여전히 쓸모 가 있 으 며,안의 Insert/Remove 두 가지 방법 으로 수정 할 수 있다.
테스트 방법
Talk is cheap, show me the code:
int docLength = 10000;
void Main()
{
(from power in Enumerable.Range (1, 16)
let mutations = (int) Math.Pow (2, power)
select new
{
mutations,
PerformanceRatio = Math.Round (GetPerformanceRatio (docLength, mutations), 1)
}).Dump();
}
float GetPerformanceRatio (int docLength, int mutations)
{
var sb = new StringBuilder ("".PadRight (docLength));
var before = GetPerformance (sb);
FragmentStringBuilder (sb, mutations);
var after = GetPerformance (sb);
return (float) after.Ticks / before.Ticks;
}
void FragmentStringBuilder (StringBuilder sb, int mutations)
{
var r = new Random(42);
for (int i = 0; i < mutations; i++)
{
sb.Insert (r.Next (sb.Length), 'x');
sb.Remove (r.Next (sb.Length), 1);
}
}
TimeSpan GetPerformance (StringBuilder sb)
{
var sw = Stopwatch.StartNew();
long tot = 0;
for (int i = 0; i < sb.Length; i++)
{
char c = sb[i];
tot += (int) c;
}
sw.Stop();
return sw.Elapsed;
}
이 코드 에 대해 다음 과 같은 몇 가 지 를 주의 하 십시오.mutations
PerformanceRatio
2
1
4
1
8
1
16
1
32
1
64
1.1
128
1.2
256
1.8
512
5.2
1024
19.9
2048
81.3
4096
274.5
8192
745.8
16384
1578.8
32768
1630.4
65536
930.8
이 를 통 해 알 수 있 듯 이 StringBuilder 중간 에 대량의 수정 을 하면 그 성능 이 급 격 히 떨 어 집 니 다.32768 번 의 수정 을 주의 깊 게 보면 한 번 에 1630.4 배 에 달 하 는 성능 이 떨 어 집 니 다!
해결 방법
StringBuilder 를 사용 해 야 한다 면 일정 횟수 를 수정 한 후에 새로운 StringBuilder 를 다시 만 드 는 것 을 고려 하여 접근 할 때 가장 좋 은 메모리 연속 성 을 얻 도록 하면 이 문 제 를 해결 할 수 있 습 니 다.
void FragmentStringBuilder (StringBuilder sb, int mutations)
{
var r = new Random(42);
for (int i = 0; i < mutations; i++)
{
sb.Insert (r.Next (sb.Length), 'x');
sb.Remove (r.Next (sb.Length), 1);
//
const int defragmentCount = 250;
if (i % defragmentCount == defragmentCount - 1)
{
string buf = sb.ToString();
sb.Clear();
sb.Append(buf);
}
}
}
위 와 같이 250 번 의 수정 을 거 칠 때마다 원래 의 StringBuilder 를 삭제 하고 새로운 StringBuilder 를 다시 만 듭 니 다.이 때 실행 효 과 는 다음 과 같 습 니 다.mutations
PerformanceRatio
2
1.2
4
0.7
8
1
16
1
32
1
64
1.1
128
1.2
256
1
512
1
1024
1
2048
1
4096
1.1
8192
1.5
16384
1.3
32768
1
65536
1
이 를 통 해 알 수 있 듯 이 거의 모든 상황 에서 메모리 의 불 연속 으로 인 한 접근 성능 문 제 를 해결 하 는 동시에 250 은 상대 적 으로 합 리 적 인 숫자 로 성능 과 조회/스 트 리밍 성능 을 삽입 하여 균형 을 잡 을 수 있다.
반성 과 총 결
string 의 불변성 으로 인해 대량의 문자열 을 연결 할 때 대량의 메모 리 를 낭비 하 는 것 은 잘 알려 져 있다.하지만 StringBuilder 를 사용 하 는 것 도 그 구 조 를 알 아야 합 니 다.
StringBuilder 가 이렇게 체인 구 조 를 만 드 는 데 는 이유 가 없 는 것 이 아니 라 삽입 성능 을 고려 하면 체인 인 터 페 이 스 를 만 드 는 것 이 가장 우수 하 다.그러나 조회 성능 을 고려 하면 체인 구 조 는 매우 불리 하 다.만약 에 비 체인 구조 로 설계 하면 중간 에 삽입 할 때 StringBuilder 의 메모리 공간 이 부족 할 수 있 기 때문에 메모 리 를 재분배 해 야 한다.이 는 StringBuilder 를 string 으로 격 하 하 하 는 것 과 같 기 때문에 StringBuilder 가'빈번 한 삽입'에 적합 하 다 는 장점 을 완전히 잃 었 다.
본 고 는 사실 매우 특수 한 예 이다.현실 에서 언어 서비스,편집 기 를 제외 하고 이런 삽입 이 빠 르 고 빠 른 장면 도 자주 수정 해 야 한다.간단하게 하려 면 StringBuilder 를 사용 하 는 것 이 조건 부 해결 방안 이 될 것 입 니 다.더 적합 한 해결 방안 은 당연히 전문 적 인 데이터 구조 인 PieceTable 입 니 다.마이크로소프트 는 VSCode 편집기 에서 큰 파일 편집 성능 을 확보 하기 위해 이 데이터 구 조 를 사용 하여 좋 은 성 과 를 거 두 었 습 니 다.링크 참조:Text Buffer Reimplementation.
StringBuilder 메모리 조각 이 성능 에 미 치 는 영향 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.StringBuilder 메모리 조각 에 관 한 더 많은 내용 은 이전 글 을 검색 하거나 아래 글 을 계속 찾 아 보 세 요.앞으로 도 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WebView2를 Visual Studio 2017 Express에서 사용할 수 있을 때까지Evergreen .Net Framework SDK 4.8 VisualStudio2017에서 NuGet을 사용하기 때문에 패키지 관리 방법을 packages.config 대신 PackageReference를 사용해야...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.