最佳缓冲流写入过程

Dan*_*uyo 3 delphi delphi-7

我们有自己的数据流算法,其中包括一些元数据+记录+字段值。

当前,我们使用TStream并编写将值添加到流中。现在我想知道是否可以通过使用某些技术来使这次加法运算更快。

编辑:我们只是将数据追加到末尾,而不是移动或查找。

我在想的一些事情是:

  • 不使用Streams buf分配一些大内存分配的缓冲区来复制数据,问题是如果我们超出了缓冲区的大小,那么我们就必须重新定位到一些新的内存空间。
  • 使用预填充#0到某个大小的流,然后开始添加值。理由是,每次执行写操作时,Tstream必须分配它自己的缓冲区(我不知道它的实际工作原理,只是想知道...)

例如,我们将字符串添加到TStream和二进制数据中,形式为#0#0#0#1。

然后,数据通过TCP传输,因此与写文件无关。

那么最好的方法是什么?

Rem*_*eau 5

首先,您假设TStream是瓶颈。您需要分析代码(例如使用AQTime),以确定瓶颈所在。不要做假设。

第二,TStream您实际使用的是哪种类型? TMemoryStreamTFileStream?还有吗 不同的流类型对内存的处理方式不同。TMemoryStream会分配一个内存缓冲区,并在缓冲区填满时将其增加预定的字节数。 TFileStream另一方面,它根本不使用任何内存,它只是直接写入文件,并让OS处理任何缓冲。

无论使用哪种类型的流,您都可以尝试实现自己的自定义TStream类,该类具有内部固定大小的缓冲区和指向实际目标TStream对象的指针。然后,您可以将自定义类的实例传递给算法。让您的类重写将TStream::Write()输入数据复制到其缓冲区中直到其填满的方法,然后可以Write()将缓冲区复制到目标TStream并清除缓冲区。您的算法永远不会知道区别。双方TMemoryStreamTFileStream会受益于额外的缓冲-大少写意味着更高效的内存分配和文件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;
Run Code Online (Sandbox Code Playgroud)

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;
Run Code Online (Sandbox Code Playgroud)

Writer := TMyBufferedStreamWriter.Create(RealStreamHere);
try
  ... write data to Writer normally as needed...
  Writer.FlushBuffer;
finally
  Writer.Free;
end;
Run Code Online (Sandbox Code Playgroud)