我们有自己的数据流算法,其中包括一些metadata+records+fields值。
目前,我们使用一个TStream和写来向流添加值。现在,我想知道这次合并操作是否可以通过使用一些技术来加快速度。
编辑:我们只是将数据追加到末尾,而不是移动或寻找。
我在想的是:
时,Tstream都必须分配它自己的缓冲区(我不知道它到底是如何工作的,只是想知道)
例如,我们正在向TStream和#0#0#0#1表单中的二进制数据中添加字符串。
然后通过TCP传输数据,所以不是写文件。
那么,最好的方法是什么呢?
发布于 2012-03-29 21:01:11
覆盖TMemoryStream并取消对大小和容量的限制。不要调用TMemoryStream.Clear,而是调用TMemoryStream.SetSize(0)
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;发布于 2012-03-29 19:53:24
首先,假设TStream是瓶颈。您需要对代码进行分析,例如使用AQTime,以确定瓶颈所在。不能主观臆断。
第二,您实际使用的是什么类型的TStream?TMemoryStream?TFileStream?还有别的吗?不同的流类型处理内存的方式不同。TMemoryStream分配内存缓冲区,并在缓冲区填满时以预先设定的字节数量增长它。另一方面,TFileStream根本不使用任何内存,它只是直接写入文件并让操作系统处理任何缓冲。
不管您使用哪种类型的流,您可以尝试的一件事是实现您自己的自定义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;发布于 2012-03-29 18:27:53
Size属性设置为足够大的数量来避免这种情况。https://stackoverflow.com/questions/9930552
复制相似问题