[Delphi] TStringBuilder

Clover·2022년 4월 6일
0

Delphi

목록 보기
9/12
post-thumbnail

델파이에서 TStringBuilder를 사용하는 방법.
그리고 꼭 사용해야만 할까? 에 대한 간단한 실험.

델파이는 "Delphi 2009" 버전부터 StringBuilder를 공식적으로 지원하기 시작했다.
(자바의 그것과 같은 개념이다.)


StringBuilder를 사용하는 이유

1. Buffer Size

일반적으로, Java 환경에서 StringBuilder를 사용하는 대표적인 이유이다.
아래 자바 코드에서 메모리의 Stack 영역과 Heap 영역의 상태 변화는 다음과 같다.

String temp = "Hello"

그림처럼 Heap 영역에 "Hello" 공간을 생성하고 포인팅을 한다.
그 다음, temp 변수에 " World" 라는 String을 이어붙이게 되면,

String temp = "Hello";
temp += " World";


"Hello World" 공간을 새로 생성한 후 포인팅을 하게 된다.

결국 "Hello" 라는 String 객체가 존재하는 Heap 영역은 낭비가 되고, 가비지 콜렉터의 제거 대상이 된다. 결국 프로그램이 조금씩 느려지게 될 것.



그래서, 아래 코드처럼 '+' 연산을 반복하는 경우에는 String보다는 StringBuilder를 사용하느 것이 전체 Buffer size 측면에서 유리하다.

String temp = '';
for (int i=0; i < 100; i++) {
    temp += "a";
}



그래서, 델파이도 마찬가지인가?

그건.. 아직은 잘 모르겠다.
구글링을 좀 해보니, 델파이의 StringBuilder는 실제 Application이 동작하면서 차지하는 메모리의 총 용량이 String 을 사용했을때와 거의 차이가 없다는 벤치마크 자료가 꽤 많이 나왔다.

직접 간단하게 App을 만들어서 Memory 사이즈를 비교해 보았는데,
수치가 너무 중구난방으로 튀어서 직접 실험한 자료는 신뢰하기가 좀 어려웠다.

그래서 이 부분은 자료를 더 찾아보아야 할 것 같다..

참조 : Stack overflow : Delphi Stringbuilder


2. 동작 속도

위의 예시 코드처럼 '+' 연산을 반복할 때, 동작 속도는 StringBuilder가 항상 더 빠른 것을 확인할 수 있었다.

테스트 코드 :
StringBuilder는 'a'를 10,000,000회 Append() 하고, String은 'a'를 '+' 연산으로 이어붙이면서 각 횟수와 동작 시간을 측정하여 표시한다.
(테스트 환경 : Windows 10 64bit, Delphi XE2)

procedure RunningTimeTest;
var
  I, Idx :Integer;
  StringBuilder :TStringBuilder;
  sString :String;
begin
  //동작 시간 비교 테스트
 
  Memo1.Lines.Add('1. TStringBuilder');
  for idx := 1 to 10 do
  begin
    StringBuilder := TStringBuilder.Create;
    WatchStart;
    try
      for I := 1 to 10000000 do
      begin
        StringBuilder.Append('a');
      end;
      WatchStop;
 
    finally
      StringBuilder.Free;
    end;
  end;
 
  Memo1.Lines.Add('');
 
  Memo1.Lines.Add('2. String');
  for idx := 1 to 10 do
  begin
    sString := '';
    WatchStart;
    for I := 1 to 10000000 do
    begin
      sString := sString + 'a';
    end;
    WatchStop;
  end;
 
end;
  • [WatchStart], [WatchStop] 프로시져는 System.DiagnosticsTStopWatch를 이용하여 직접 구현한 것임.

동작화면 : (단위 : sec)

  • 동작 시간은 StringBuilder가 더 빠른것을 확인해볼 수 있었다.

그러나 유의할 점이 있는데, 실제 동작 환경에 따라서는 String이 더 빠를수도 있다는 것이다. (...)

첫번째로, 위의 테스트는 반복 횟수를 1천만번으로 설정한 케이스라는 점이 문제다.
1천만번 반복 동작마다 시간 차이가 0.03초 정도밖에 차이가 나지 않는다는 것은,
실제 운영 코드가 문자열을 이어붙이는 반복을 1천만번씩 하는 경우가 아니라면 둘의 차이가 유의미할 정도로 크게 나지는 않을 것이다.
다시 말해서, 반복 횟수가 줄어들수록 동작속도 차이도 줄어든다는 것..


그리고,
위처럼 'a'라는 단일 문자에 대한 측정은 StringBuilder가 우세했지만,
문자열이 길어질수록 String이 동작속도가 빨라진다는 것도 확인해볼 수 있었다.

StringBuilder.Append('asdfasdf');
...
...
 
sString := sString + 'asdfasdf';

위처럼 'asdfasdf'를 이어붙이도록 코드를 바꾸고 테스트 해본 결과,

String이 더 빠르게 동작하는 것을 확인해볼 수 있었다.


기대한건 이게 아닌데

결론은.. 딱히 TStringBuilder를 써야만 하는 이유는 찾을 수 없었다.
Java에서는 메모리와 동작속도 측면에서 StringBuilder가 더 유리한 부분이 있다고 배웠었는데..
Java에서의 장점을 기대하고 사용하기에는 부적합한 것 같다는 결론이다.

결국 델파이에서는 String보다 더 나아보이는 점은 없다고 결론을 내렸다.

오래 된 델파이 버전을 사용해서 그런걸수도 있겠다는 생각이 들긴 했으나, 지금 내 업무 환경에서는 XE2보다 상위 버전을 사용할 일이 없어서..
기회가 된다면 동일한 코드를 최신 델파이 환경에서 다시 테스트 해보고 싶긴 하다.

0개의 댓글