这是我关于 SO 的第二个问题,我希望我的格式正确。
我在工作中发现 TFileStream 比 TMemoryStream 慢,我真的不知道为什么会这样。因此我决定做一些测试。
在我发现这种行为的应用程序中,我将所有文件加载到一个文件夹中,并且对于每个文件,我必须逐字节读取它。从 TFileStream
切换到 TMemoryStream
后,执行变得同步。为了测试这个,我做了下面的函数,其中相同的文件 (FileName
) 被加载到 TStream
Nr
次,每次流一次读取 Siz
字节直到结束(我真的很抱歉我的英语)。
我用来测试的功能是:
第一个是对TFileStream
的测试,因为它没有LoadFromFile
方法,我每次都必须创建和销毁它。
function TestFileStream(Nr, Siz: Integer): Double;
var
sw: TStopWatch;
Stream: TFileStream;
I: Integer;
buffer: TBytes;
begin
sw := TStopWatch.StartNew;
System.SetLength(buffer, Siz);
for I := 0 to Nr - 1 do
begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
Stream.Position := 0;
while Stream.Position + Siz < Stream.Size do
Stream.ReadBuffer(buffer, Siz);
finally
Stream.Free;
end;
end;
Result := sw.Elapsed.TotalSeconds;
sw.Stop;
end;
第二个是对TMemoryStream
的测试,同样这次TMemoryStream
被创建和销毁了Nr
次。
function TestMemoryStream(Nr, Siz: Integer): Double;
var
sw: TStopWatch;
Stream: TMemoryStream;
I: Integer;
buffer: TBytes;
begin
sw := TStopWatch.StartNew;
System.SetLength(buffer, Siz);
for I := 0 to Nr - 1 do
begin
Stream := TMemoryStream.Create;
try
Stream.LoadFromFile(FileName);
Stream.Position := 0;
while Stream.Position + Siz < Stream.Size do
Stream.ReadBuffer(buffer, Siz);
finally
Stream.Free;
end;
end;
Result := sw.Elapsed.TotalSeconds;
sw.Stop;
end;
第三个是TMemoryStream
的测试,这次TMemoryStream
只创建了一次。
function TestKeepMemoryStream(Nr, Siz: Integer): Double;
var
sw: TStopWatch;
Stream: TMemoryStream;
I: Integer;
buffer: TBytes;
begin
sw := TStopWatch.StartNew;
System.SetLength(buffer, Siz);
Stream := TMemoryStream.Create;
try
for I := 0 to Nr - 1 do
begin
Stream.LoadFromFile(FileName);
Stream.Position := 0;
while Stream.Position + Siz < Stream.Size do
Stream.ReadBuffer(buffer, Siz);
end;
finally
Stream.Free;
end;
Result := sw.Elapsed.TotalSeconds;
sw.Stop;
end;
结果如下:
Nr = 100, Siz = 1
TFileStream: 27,8980448s
TMemoryStream: 0,1571709s
TMemoryStream Kept: 0,1607682s
Nr = 100, Siz = 16
TFileStream: 1,7674029s
TMemoryStream: 0,044709s
TMemoryStream Kept: 0,0432958s
Nr = 100, Siz = 4096
TFileStream: 0,0427971s
TMemoryStream: 0,0325959s
TMemoryStream Kept: 0,0316288s
令我感到奇怪的是 TMemoryStream
使用 TFileStream
加载文件,而 ReadBuffer
方法继承自 TStream
,所以就我的理解而言,应该没有区别。你有什么想法可以解释这一点吗?
最佳答案
如果您的 Siz
参数很小,TFileStream
每次都会访问磁盘以读取非常小的数据 block ,而在您的代码中 TMemoryStream
访问磁盘一次,然后从内存中读取小块。如果您将 Siz
变量设置为磁盘上文件的大小,您应该看不出有什么不同。
https://stackoverflow.com/questions/74150678/
相关文章:
javascript - 警告 IE11 用户他们的浏览器在 React 18 中不受支持
c# - ocelot api网关中的System.InvalidOperationExceptio
r - R中,如果有多个TRUE答案,选择第一个TRUE答案
c# - .NET 6 将参数检查替换为 ArgumentNullException.ThrowIf
javascript - 在 Javascript 中没有双 for 循环的情况下用对象数组中的 0
typescript - 如何为 Prisma 选择属性键入变量