From YYpBD's MediaWiki
[팁] TMemorySteram 속도 최적화..
밑에 병규님 글과는 전혀 반대되는 글인데요..
메모리를 희생시켜서, 속도를 얻는 방법에 대해서 써볼까 합니다..^_^;;
대용량 작업을 할때 TMemoryStream 이 발생시키는 오버헤드가 상당히 큽니다.
어느정도로 큰가 하면..백문이 불여 일견이라고 일단 소스를 보시죠..
procedure TForm1.Button1Click(Sender: TObject);
const
SIZE = 10 * 1024 * 1024; // 10M
var
i: Integer;
ms: TStream;
t: DWord;
begin
t := TimeGetTime;
ms := TMemoryStream.Create;
try
// 이부분이 중요함!
// ms.size := SIZE;
// ms.Position := 0;
for i := 1 to SIZE div sizeof(i) do // 10M
ms.Write(i, sizeof(i));
finally
ms.Free;
end;
showmessage(inttostr(TimeGetTime - t));
end;
10메가 데이터를 메모리 스트림에 기록하는 속도를 보여주는 소스입니다.
공간을 확보하지 않음(주석처리 했을때): 25507(약 25초)
공간을 미리 확보(주석처리 안했을때): 378 (약 0.4초)
속도차이가 이렇게 엄청나게 나는 이유는, 메모리스트림은 사이즈가 변할때마다 메모리 재할당, 기존 내용을 카피 작업이 이루어지기 때문입니다. TList 가 속도에 최적화되어서, 재할당 횟수를 최소로 줄인것과는 반대로, 메모리 스트림은 메모리를 아끼는 구조로 되어있기는 한데, 오버헤드가 큽니다. 속도가 O(n^2) 이 되어버려서..크기가 클수록 시간은 엄청나게 더 걸리게 되지요....
고로, 메모리 스트림을 이용해서 빠른 속도로 작업을 하려면 미리 넉넉한 양의 메모리를 확보한 후에 작업을 하는것이 좋겠죠.
쓰는김에 파일 스트림에 대한 얘기도 좀 하겠습니다.
스트림 생성 부분을
ms := TFileStream.Create('test.bin', fmcreate);
이렇게 만 바꾸고 테스트 하면 어떤 결과가 나올까요?
공간 확보 않음 - 6293
공간 미리 확보 - 6197
오차가 좀 있긴 하지만, 거의 같은 결과가 나옵니다. (아마도 디스크 캐쉬의 영향이 클듯 합니다. 그런데, 메모리 다루는 작업이 파일 다루기보다 느리다니, 이정도면 상당히 오버헤드가 심하다는걸 알 수 있습니다.)
파일이니 만큼 사이즈를 좀 더 늘려놓고 실험을 해봅시다. 파일 사이즈를 100M 로 늘린경우는 어떨까요?
공간 확보 않음 - 63154
공간 미리 확보 - 61435
뭐 디스크 성능과 캐쉬 사이즈에 따라 차이는 있겠지만, 그래도 비슷합니다. 그렇다면, 파일 스트림은 미리 사이즈를 확보하는 작업이 불필요한것인가? 그게 또 그렇지가 않습니다. 2000 이상이신 분들은 Disk Defragment 툴을 띄우고, 분석 버튼을 누른 후 test.bin 파일을 찾아봅시다.
공간 확보 않음 - 990 조각
공간 미리 확보 - 없음(조각나지 않음)
디스크 사정에 따라 다르겠지만, 확실히 미리 공간을 확보하는쪽이 하드 정리가 예쁘게 됩니다.. 소리바다로 받은 MP3파일이 항상 수백조각 나있는 이유가 아마도 이런것이겠죠.. 뭐 겉보기에는 비슷하게 동작합니다만, 꼼꼼한 프로그래머 라면 프로젝트에 적용시켜볼만한 테크닉이 아닌가 합니다..
시간 나시는 분들은 TList 의 Grow 방식으로 메모리를 할당하는 메모리 스트림을 만들어 보는것도 좋지 않을까 합니다..
그럼 다들 즐푸하십시오-