为什么Delphi zlib和zip库在64位之下这么慢? [英] Why are the Delphi zlib and zip libraries so slow under 64 bit?

查看:140
本文介绍了为什么Delphi zlib和zip库在64位之下这么慢?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在对现实世界的应用进行基准测试时,我遇到了与Delphi一起提供的zlib和zip库的令人惊讶的性能特征。

Whilst benchmarking a real-world application I came across a surprising performance characteristic relating to the zlib and zip libraries that ship with Delphi.

我的真实应用程序导出.xlsx文件。这个文件格式是一个包含在ZIP容器文件中的XML文件的集合。 .xlsx导出代码生成XML文件,然后将其提供给Delphi ZIP库。一旦我优化了XML文件生成到ZIP创建是我发现的瓶颈,我感到惊讶的是,64位代码明显慢于32位代码。

My real-world application exports .xlsx files. This file format is a collection of XML files wrapped in a ZIP container file. The .xlsx export code generates the XML files and then feeds them to the Delphi ZIP library. Once I had optimised the XML file generation to the point where the ZIP creation was the bottleneck I discovered, to my surprise, that 64 bit code was significantly slower than 32 bit code.

为了进一步研究,我创建了这个测试程序:

In order to study this further I created this test program:

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.

我在XE2和XE7下编译了32位和64位的程序,默认版本配置编译器选项。我的测试机器在Intel Xeon E5530上运行Windows 7 x64。

I compiled the program under both XE2 and XE7, for both 32 and 64 bit, and with default release configuration compiler options. My test machine runs Windows 7 x64 on an Intel Xeon E5530.

结果如下:


Compiler  Target  Time (ms)
     XE2   Win32       8586
     XE2   Win64      18908
     XE7   Win32       8583
     XE7   Win64      19304

我使用Explorer shell ZIP功能压缩了同一个文件,我粗略的停止观看时间是8秒,所以上面的32位时间似乎是合理的。

I compressed the same file using the Explorer shell ZIP functionality and my rough stop watch timing was 8 seconds so the 32 bit times above seem reasonable.

由于上述代码使用的压缩算法是zlib(Delphi的ZIP代码仅支持存储和缩小),我的信念是Delphi使用的zlib库是此问题的根源。为什么Delphi的zlib库在64位以下这么慢?

Since the compression algorithm used by the above code is zlib (Delphi's ZIP code supports only store and deflate), my belief is that the zlib library used by Delphi is at the root of this issue. Why is Delphi's zlib library so slow under 64 bit?

推荐答案

如前所述,Delphi ZIP压缩代码站在zlib之上。 zlib的Delphi实现是官方zlib C源代码的封装。 C代码被编译成对象,然后与 {$ LINK} 链接。对于XE7, System.ZLib 顶部的注释表示使用了zlib 1.2.8。

As noted, the Delphi ZIP compression code stands on top of zlib. The Delphi implementation of zlib is a wrapper around the official zlib C source code. The C code is compiled to objects and then linked with {$LINK}. For XE7, the comments at the top of System.ZLib indicate that zlib 1.2.8 was used.

下在zlib代码中花费时间的明显假设是对行为最合理的解释是64位编译对象对性能不佳负责。所使用的编译器是发出弱码,或者使用了编译器选项的不良选择。

Under the obvious assumption that the time is being spent inside the zlib code, the most plausible explanation for the behaviour is that the 64 bit compiled objects are responsible for the poor performance. Either the compiler used is emitting weak code, or a poor choice of compiler options has been used.

所以,我采取了以下步骤:

So, I took the following steps:


  1. 我下载了zlib 1.2.8的源代码,并使用Microsoft 64位编译器cl编译。

  2. 使用VS2010编译器,版本16.00.30319.01。我使用以下选项编辑对象: / O2 / GS -

  3. 然后我再次获取了一个 System.ZLib.pas 的副本,并将其包含在我的项目中,以及新编译的对象。这样可以确保使用新编译的zlib对象。

  4. 我用XE7编译了64位的Delphi程序。

  1. I downloaded the source for zlib 1.2.8 and compiled with the Microsoft 64 bit compiler, cl.
  2. Using the VS2010 compiler, version 16.00.30319.01. I compiled the objects with the following options: /O2 /GS-.
  3. I then took a copy of System.ZLib.pas and included it in my project, alongside the newly compiled objects. This ensures that the newly compiled zlib objects are used.
  4. I compiled the Delphi program with XE7 for 64 bit.

运行时间与在问题中生成数据的同一台机器上是6,912ms。

The run time, on the same machine as used to generate the data in the question was 6,912ms.

然后,我重新编译并省略了 / O2 选项,再循环一遍。这次运行时间为20,077ms。所以我假设Embarcadero刚刚忘记使用优化来编译这些对象。

I then recompiled and omitted the /O2 option and went round the loop again. This time the run time was 20,077ms. So I hypothesise that Embarcadero have just been forgetting to compile these objects with optimisations.

我已经向Embarcadero的质量门户报告了这个问题: https://quality.embarcadero.com/browse/RSP-9891

I have reported this issue to Embarcadero's Quality Portal: https://quality.embarcadero.com/browse/RSP-9891

如下面的评论所述,依靠编译对象的其他库似乎也有类似的问题。潜在的问题领域包括:

As mentioned in a comment below, it seems quite plausible that other libraries that rely on compiled objects may have similar problems. Potential problem areas include:


  • MidasLib,对象可能不是性能关键。

  • Indy,版本与Delphi一起使用相同的zlib对象。

  • System.RegularExpressions是PCRE周围的一个包装。

  • Vcl.Imaging.jpeg在作为编译对象链接的第三方JPEG实现之上。

  • MidasLib, objects are probably not performance critical.
  • Indy, the version shipped with Delphi uses the same zlib objects I believe.
  • System.RegularExpressions, a wrapper around PCRE.
  • Vcl.Imaging.jpeg, built on top of a 3rd party JPEG implementation that is linked as compiled objects.

更新

质量门户问题报告说,此问题在XE8中已修复。

The Quality Portal issue reports that this issue was fixed in XE8.

这篇关于为什么Delphi zlib和zip库在64位之下这么慢?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆