Во-первых, вы предполагаете, что TStream
является узким местом.Вам нужно профилировать свой код, например, с помощью AQTime, чтобы определить, где на самом деле находится узкое место.Не делайте предположений.
Во-вторых, какой тип TStream
вы на самом деле используете?TMemoryStream
?TFileStream
?Что-то другое?Различные типы потоков обрабатывают память по-разному.TMemoryStream выделяет буфер памяти и увеличивает его на заранее установленное количество байтов всякий раз, когда буфер заполняется.TFileStream
, с другой стороны, вообще не использует никакой памяти, он просто записывает непосредственно в файл и позволяет ОС обрабатывать любую буферизацию.
Независимо от того, какой тип потока вы используете, одна вещьВы можете попробовать реализовать собственный пользовательский класс TStream
, который имеет внутренний буфер фиксированного размера и указатель на объект TStream
вашего реального назначения.Затем вы можете передать экземпляр вашего пользовательского класса в свой алгоритм.Попросите ваш класс переопределить метод TStream::Write()
, чтобы скопировать входные данные в его буфер, пока он не заполнится, тогда вы можете Write()
буфер до места назначения TStream
и очистить буфер.Ваш алгоритм никогда не узнает разницу.И TMemoryStream
, и TFileStream
выиграют от дополнительной буферизации - меньшее количество больших записей означает более эффективное распределение памяти и файловый ввод / вывод.Например:
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;