먼저, TStream
이 병목 현상이라고 가정합니다. AQTime과 같은 코드를 프로파일 링하여 병목 현상이 실제로 어디에 있는지 파악해야합니다. 가정하지 마십시오.
두 번째로 실제로 사용하고있는 TStream
의 유형은 무엇입니까? TMemoryStream
? TFileStream
? 다른 것? 다른 스트림 유형은 메모리를 다르게 처리합니다. TMemoryStream은 메모리 버퍼를 할당하고 버퍼가 채워질 때마다 미리 설정된 크기만큼 메모리 버퍼를 늘립니다. 반면에 TFileStream
은 메모리를 전혀 사용하지 않고 단지 파일에 직접 씁니다. 그리고 OS가 버퍼링을 처리하게합니다.
사용하는 스트림의 유형에 관계없이 시도해 볼 수있는 한 가지 방법은 내부 고정 크기 버퍼와 실제 대상인 TStream
개체에 대한 포인터가있는 사용자 지정 TStream
클래스를 구현하는 것입니다. 그런 다음 사용자 정의 클래스의 인스턴스를 알고리즘에 전달할 수 있습니다. 클래스가 가득 채워질 때까지 TStream::Write()
메서드를 재정 의하여 해당 입력 데이터를 버퍼에 복사 한 다음 Write()
버퍼를 대상에 TStream
버퍼로 지울 수 있습니다. 귀하의 알고리즘은 그 차이를 결코 알 수 없습니다. TMemoryStream
과 TFileStream
모두 추가 버퍼링의 이점을 누릴 수 있습니다. 쓰기가 적을수록 메모리 할당과 파일 I/O가 더 효율적이라는 의미입니다.예 :
type
TMyBufferedStreamWriter = class(TStream)
private
fDest: TStream;
fBuffer: array[0..4095] of Byte;
fOffset: Cardinal;
public
constructor Create(ADest: TStream);
function Read(var Buffer; Count: Longint): Longint; override;
function Write(const Buffer; Count: Longint): Longint; override;
procedure FlushBuffer;
end;
.
uses
RTLConsts;
constructor TMyBufferedStreamWriter.Create(ADest: TStream);
begin
fDest := ADest;
end;
function TMyBufferedStreamWriter.Read(var Buffer; Count: Longint): Longint;
begin
Result := 0;
end;
function TMyBufferedStreamWriter.Write(const Buffer; Count: Longint): Longint;
var
pBuffer: PByte;
Num: Cardinal;
begin
Result := 0;
pBuffer := PByte(@Buffer);
while Count > 0 do
begin
Num := Min(SizeOf(fBuffer) - fOffset, Cardinal(Count));
if Num = 0 then FlushBuffer;
Move(pBuffer^, fBuffer[fOffset], Num);
Inc(fOffset, Num);
Inc(pBuffer, Num);
Dec(Count, Num);
Inc(Result, Num);
end;
end;
procedure TMyBufferedStreamWriter.FlushBuffer;
var
Idx: Cardinal;
Written: Longint;
begin
if fOffset = 0 then Exit;
Idx := 0;
repeat
Written := fDest.Write(fBuffer[Idx], fOffset - Idx);
if Written < 1 then raise EWriteError.CreateRes(@SWriteError);
Inc(Idx, Written);
until Idx = fOffset;
fOffset := 0;
end;
.
Writer := TMyBufferedStreamWriter.Create(RealStreamHere);
try
... write data to Writer normally as needed...
Writer.FlushBuffer;
finally
Writer.Free;
end;
메모리 스트림에 대해 이야기하고 계십니까? –
데이터 양이 많으면 (200MB 이상) TFileStream을 권장합니다. 그렇지 않으면 TMemoryStream이 가장 빠르고 쉬운 방법입니다. TFile | MemoryStream을 사용하고 (레코드 수 등) 정보를 유지해야하는 경우 스트림 시작 부분에 헤더를 추가하고 모든 업데이트 후에 커서 위치를 처음으로 재설정 한 다음 스트림을 읽고 오버라이드하십시오. 위치 : = Stream.Size; <- bam 스트림의 끝에 있고 데이터를 계속 추가합니다. 레코드 삭제의 가능성이있는 경우 각 레코드에는 플래그 (삭제됨 : Boolean)가 포함 된 헤더가 필요합니다. – ComputerSaysNo
@Dorin : 우리는 소켓을 사용하여 보내기 때문에 TFileStream이 옵션이 아닌 것으로 보입니다. 문제는 스트림 + 쓰기를 사용하여 수행하는 방법이 아닙니다. 이미 사용하고 있습니다. 문제는 더 빠르게 수행 할 수있는 방법이있는 경우입니다. –