-
반응형
string vs stringbuilder
기존 C#의 string은 참조 타입이며 수정을 하게 되면 새로운 string 객체가 생기고 새 객체로 대체되는 형식입니다. 이와 동시에 이전 객체는 남아있게 되어 GC 대상이 됩니다. 때문에 자주 변경될 문자열이라면 stringbuilder를 사용해야 한다는 이야기입니다.
왜 string은 immutable이 되었을까?
이는 string이 immutable 객체로 만들어져 있어서 한번 값이 정해진 뒤 수정을 할 수 없기 때문입니다. 그러면 왜 이렇게 변경할 수 없는 객체로 만들어서 가비지를 생성하는, 겉보기에 비효율적인 방법을 체택했을까요?
.Net 에서 string이 변경 불가능 객체인 이유는 멀티스레드 환경을 고려한게 커 보입니다. 여러 프로세스가 엑세스를 하게 되면 경쟁 상태가 될 수 있고 이로 인해서 lock을 걸어야 하는 등의 부가적인 사항들이 들어가게 됩니다. 대신 변경이 안되므로 이런 것들을 고려할 필요가 없게 되는 것이죠.
추가로 값이 변경되지 않으므로 값 타입처럼 비교를 할 수 있다는 장점이 있다고 합니다.
stringbuilder는 정말 가비지를 생성하지 않는가
그러면 일단 string을 변경하면 새 객체가 생성되어 이전 객체는 가비지가 된다... 이건 알았고 stringbuilder는 어떤 식이라 가비지 생성이 없는 걸까요?
일단 stringbuilder는 16문자 크기의 자리를 잡게 됩니다. 물론 인자를 줘서 처음 크기를 다르게 잡을 수도 있죠. 일단 기본적으로 제공되는 16크기의 문자를 만들고 이를 꽉 채웠다고 합시다. 이동안 stringbuilder에서 가비지를 생성하지 않습니다. 기존에 가지고 있는 곳에서 어찌저찌 잘 하면 되거든요.
이제 꽉 채운 상태에서 append를 하게 되면 더 큰 용량의 버퍼가 잡히게 되고 원래 버퍼의 데이터가 새 버퍼에 복사되는 과정이 필요하게 됩니다. 이 과정에서 이전의 버퍼는 GC의 먹이가 되는 것이죠.
...가 닷넷 4.0까지의 이야기라고 합니다. 지금은 새 버퍼를 할당한 뒤 링크를 구성한다고 합니다. 때문에 복사, 이전 버퍼가 가비지가 되는 등의 일은 없어져 성능이 이전보다 좋아졌다는 것입니다.
마지막으로 tostring 메서드를 부르게 되면 버퍼에 있는 저장된 문자열을 복사한 뒤 새 문자열 string을 만들기 때문에 이 과정에서도 비용이 들게 됩니다. 그래서 처음에 용량을 정해줄 수 있으면 미리 정해서 버퍼가 복사되는 과정을 피하는게 좋습니다. 그리고 문자열의 변경을 자주 하게 되는 경우에 string과 stringbuilder의 성능 차이를 확실히 알아본 뒤 사용하는게 좋습니다.
참고자료
- 왜 string이 불변인가에 대한 이야기 (단 첫 사유는 이해가 잘 안됩니다)
- stringbuilder 메모리에 관한 이야기
반응형'쾌락없는 책임 (공부) > C# 짜잘이' 카테고리의 다른 글
[C#] is null vs == null (0) 2023.01.15 [C#] C# 에서 상호 참조는 어떻게 해결이 될까? (0) 2022.08.06