首先,假设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 17:56:55
如果数据量很大(比如超过200MB),那么我推荐一个TFileStream,否则TMemoryStream会是最快最容易的方式。如果您选择使用TFile | MemoryStream并且您需要保留信息(记录计数等),请在Stream的开头添加一个标题,并在每次更新后将光标位置重置为开头,读取并覆盖Stream的标题。位置:= Stream.Size; < - bam你在流的末尾,继续追加数据。如果有任何删除记录的机会,那么每条记录都需要一个包含标志的标题(Deleted:Boolean) – ComputerSaysNo 2012-03-29 18:23:39
@Dorin:我们使用套接字发送,所以TFileStream似乎不是一个选项。问题不在于如何使用stream + write来做到这一点,我们已经在使用它,问题是如果有一些方法可以更快地做到这一点。 – 2012-03-29 19:09:52