首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >最优缓冲流写入过程

最优缓冲流写入过程
EN

Stack Overflow用户
提问于 2012-03-29 17:41:06
回答 3查看 2.6K关注 0票数 3

我们有自己的数据流算法,其中包括一些metadata+records+fields值。

目前,我们使用一个TStream和写来向流添加值。现在,我想知道这次合并操作是否可以通过使用一些技术来加快速度。

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

我在想的是:

  • 不使用流buf -一些分配给数据的大内存缓冲区复制数据,问题是如果我们超出缓冲区大小,那么我们必须重新定位到一些新的内存空间。
  • 使用预先填充#0的流到某种大小,然后开始添加值。其基本原理是,每次编写

时,Tstream都必须分配它自己的缓冲区(我不知道它到底是如何工作的,只是想知道)

例如,我们正在向TStream和#0#0#0#1表单中的二进制数据中添加字符串。

然后通过TCP传输数据,所以不是写文件。

那么,最好的方法是什么呢?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-03-29 21:01:11

覆盖TMemoryStream并取消对大小和容量的限制。不要调用TMemoryStream.Clear,而是调用TMemoryStream.SetSize(0)

代码语言:javascript
复制
type
  TMemoryStreamEx = class(TMemoryStream)
  public
    procedure SetSize(NewSize: Longint); override;
    property Capacity;
  end;

implementation

{ TMemoryStreamEx }

procedure TMemoryStreamEx.SetSize(NewSize: Integer);
var
  OldPosition: Longint;
begin
  if NewSize > Capacity then
    inherited SetSize(NewSize)
  else
  begin
    OldPosition := Position;
    SetPointer(Memory, NewSize);
    if OldPosition > NewSize then
      Seek(0, soFromEnd);
  end;
end;
票数 2
EN

Stack Overflow用户

发布于 2012-03-29 19:53:24

首先,假设TStream是瓶颈。您需要对代码进行分析,例如使用AQTime,以确定瓶颈所在。不能主观臆断。

第二,您实际使用的是什么类型的TStreamTMemoryStreamTFileStream?还有别的吗?不同的流类型处理内存的方式不同。TMemoryStream分配内存缓冲区,并在缓冲区填满时以预先设定的字节数量增长它。另一方面,TFileStream根本不使用任何内存,它只是直接写入文件并让操作系统处理任何缓冲。

不管您使用哪种类型的流,您可以尝试的一件事是实现您自己的自定义TStream类,该类具有一个内部固定大小的缓冲区和一个指向实际目标TStream对象的指针。然后,可以将自定义类的实例传递给算法。让类重写TStream::Write()方法将输入数据复制到它的缓冲区中,直到它被填满为止,然后可以将缓冲区Write()到目标TStream并清除缓冲区。你的算法永远不会知道区别。TMemoryStreamTFileStream都将受益于额外的缓冲--更少的大写入意味着更高效的内存分配和文件I/O,例如:

代码语言:javascript
复制
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;

代码语言:javascript
复制
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;

代码语言:javascript
复制
Writer := TMyBufferedStreamWriter.Create(RealStreamHere);
try
  ... write data to Writer normally as needed...
  Writer.FlushBuffer;
finally
  Writer.Free;
end;
票数 5
EN

Stack Overflow用户

发布于 2012-03-29 18:27:53

  1. 使用分析器来查看实际速度慢的地方。
  2. 如果确实是由于多次重新分配来增加流的大小,则可以通过预先将Size属性设置为足够大的数量来避免这种情况。
  3. 使用内存缓冲区的唯一不同之处在于,如果您使用的是FileStreams,所有其他可用的流都已经在为您执行此操作。
票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/9930552

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档