Во время тестирования реального приложения я столкнулся с удивительной характеристикой производительности, связанной с библиотеками zlib и zip, которые поставляются с Delphi.
My real-world приложение экспортирует файлы .xlsx. Этот формат файла представляет собой набор файлов XML, завернутых в файл контейнера ZIP. Экспортный код .xlsx генерирует файлы XML, а затем передает их в ZIP-архив Delphi. Как только я оптимизировал генерацию файла 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.
Я скомпилировал программу как для XE2, так и для XE7, для 32 и 64 бит, а также для параметров компилятора конфигурации по умолчанию. Моя тестовая машина работает под управлением Windows 7 x64 на Intel Xeon E5530.
Вот результаты:
Compiler Target Time (ms) XE2 Win32 8586 XE2 Win64 18908 XE7 Win32 8583 XE7 Win64 19304
Я сжал один и тот же файл, используя функциональность ZIP-оболочки обозревателя, и мое грубое время остановки секундомера составляло 8 секунд, поэтому 32-битные времена выше кажутся разумными.
Поскольку алгоритм сжатия, используемый вышеуказанным кодом, является zlib (индексный код Delphi поддерживает только сохранение и дефляцию), я считаю, что библиотека zlib, используемая Delphi, лежит в основе этой проблемы. Почему библиотека Delphi zlib настолько медленная до 64 бит?