Dav*_*nan 17 delphi delphi-xe2 delphi-xe7
在对现实世界的应用程序进行基准测试时,我遇到了与Delphi附带的zlib和zip库相关的令人惊讶的性能特征.
我的实际应用程序导出.xlsx文件.此文件格式是包含在ZIP容器文件中的XML文件的集合..xlsx导出代码生成XML文件,然后将它们提供给Delphi ZIP库.一旦我将XML文件生成优化到ZIP创建是我发现的瓶颈,令我惊讶的是,64位代码明显慢于32位代码.
为了进一步研究这个,我创建了这个测试程序:
program zlib_perf;
{$APPTYPE CONSOLE}
uses
System.SysUtils, System.Classes, System.Diagnostics, System.Zip;
const
LoremIpsum =
'Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod '+
'tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, '+
'quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo '+
'consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse '+
'cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat '+
'non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.';
function GetTestStream: TStream;
var
Bytes: TBytes;
begin
Result := TMemoryStream.Create;
// fill the stream with 500MB of lorem ipsum
Bytes := TEncoding.UTF8.GetBytes(LoremIpsum);
while Result.Size < 500*1024*1024 do
Result.WriteBuffer(Pointer(Bytes)^, Length(Bytes));
end;
procedure DoTest;
var
DataStream, ZipStream: TStream;
Stopwatch: TStopwatch;
Zip: TZipFile;
begin
DataStream := GetTestStream;
try
ZipStream := TMemoryStream.Create;
try
Zip := TZipFile.Create;
try
Zip.Open(ZipStream, zmWrite);
Stopwatch := TStopwatch.StartNew;
DataStream.Position := 0;
Zip.Add(DataStream, 'foo');
Writeln(Stopwatch.ElapsedMilliseconds);
finally
Zip.Free;
end;
finally
ZipStream.Free;
end;
finally
DataStream.Free;
end;
end;
begin
DoTest;
end.
Run Code Online (Sandbox Code Playgroud)
我在XE2和XE7下编译了32位和64位的程序,以及默认的发布配置编译器选项.我的测试机在Intel Xeon E5530上运行Windows 7 x64.
结果如下:
Compiler Target Time (ms)
XE2 Win32 8586
XE2 Win64 18908
XE7 Win32 8583
XE7 Win64 19304
我使用Explorer shell ZIP功能压缩了同一个文件,我的粗略秒表定时为8秒,因此32位以上似乎合理.
由于上面代码使用的压缩算法是zlib(Delphi的邮政编码仅支持存储和收缩),我相信Delphi使用的zlib库是这个问题的根源.为什么Delphi的zlib库在64位下如此之慢?
Dav*_*nan 21
如上所述,Delphi ZIP压缩代码位于zlib之上.zlib的Delphi实现是官方zlib C源代码的包装.C代码被编译为对象然后链接{$LINK}.对于XE7,顶部的注释System.ZLib表示使用了zlib 1.2.8.
在zlib代码中花费时间的明显假设下,对行为最合理的解释是64位编译对象导致性能不佳.要么使用的编译器发出弱代码,要么使用了很差的编译器选项.
所以,我采取了以下步骤:
/O2 /GS-.System.ZLib.pas并将其包含在我的项目中,以及新编译的对象.这可确保使用新编译的zlib对象.在用于生成问题中的数据的同一台机器上的运行时间为6,912ms.
然后我重新编译并省略了该/O2选项并再次绕过循环.这次运行时间为20,077毫秒.所以我假设Embarcadero忘记用优化编译这些对象.
我已将此问题报告给Embarcadero的质量门户网站:https://quality.embarcadero.com/browse/RSP-9891
正如下面的评论中所提到的,依赖于编译对象的其他库可能会遇到类似的问题.潜在的问题领域包括:
更新
质量门户问题报告此问题已在XE8中得到修复.