понедельник, 5 марта 2007 г.

Delphi 2007 (часть II - строковые функции)

Тема

В Delphi 2007 оптимизированы следующие строковые функции:

  1. UpperCase
  2. LowerCase
  3. CompareStr
  4. StrLen
  5. _LStrCmp

Мои исследования

Т.к. я чаще всего пользуюсь сравнением строк (оператор стравнения), то мне наиболее интересно было посмотреть разницу выполнения функции _LStrCmp (именно она в конце концов вызывается при сравнении двух строк if S1 = S2 then ...).

Построив свой первый тест производительности я был удивлен (огорчен), что в BDS 2006 и Delphi 2007 выполнение теста сопостовимо по времени.

Тут я подумал, что не может быть такого - процедуру переписали (вроде это кто-то делал из проекта fastcode - точно я не в курсе ибо не интересуюсь данным проектом), а скорость примерно та же.

Поэтому я полез в исходники и обнаружил, что оптимизация проведена для определенных случаев. Скорость выполнение операции сравнения строк повысилась в случае:

  1. Сравнения строк, если одна (или обе) из них пустая.
  2. Сравнение строк, которые отличаются первым символом.

Я построил еще один тест. Суть теста 10^9 сравнений случайных строк длины 10 со случайной строкой такой же длины.

{$o+}{$r-}{$q-}
program StringFunctionsTest3;
{$APPTYPE CONSOLE}
uses
SysUtils, Windows;
const
cLen = 1000000;
cStrLen = 10;
cTests = 1000;
var
I,J: Integer;
A: array [0..cLen-1] of String;
PF, PC1, PC2: TLargeInteger;
S: String;
begin
QueryPerformanceFrequency(PF);
for I := 0 to cLen - 1 do
begin
A[I] := '';
for J := 0 to cStrLen-1 do
A[I] := A[I]+Chr(32+Random(60));
end;
S := A[cLen-1];
QueryPerformanceCounter(PC1);
for J := 0 to cTests - 1 do
for I := 0 to cLen - 1 do
if A[I] = S then
Break;
QueryPerformanceCounter(PC2);
WriteLn(Format('%.4f', [(PC2-PC1)/PF]));
ReadLn;
end.
По результатам проверки в BDS 2006 и Delphi 2007 обнаружено ускорение от 30% до 50%.

Также я провел замеры скорости выполнения при сравнении строк, когда одна из них пустая. Также обнаружено ускорение от 30% до 50%.

Данная доработка не может не радовать ибо, во-первых, среда в целом будет работать быстрее, во-вторых, наши с вами программы будут работать быстрее.

2 комментария:

Анонимный комментирует...

Процедура сравнения (равенство-неравенство) строк крайне не оптимальна, если написать собственную, то выйгрыш будет раз в 10 и больше.

1) Сначала сравнить длины строк
2) Сравнения проводить в цикле посимвольно с конца строки (начала строк часто совпадают)

Оптимизатор сделал свое дело достойно, скорость XSameStr(s1, s2) более чем 10 раз превзошла s1 = s2.
Думаю создание такого кода под силу ЛЮБОМУ программисту.

Дмитрий Тимохов комментирует...

Ровно такая доработка есть в quality central. Номер доработки сейчас лень искать. Но доработка открыта к выполнению. Наверное в HighLander'е сделают.

Насколько я понял, они были готовы данную доработку сделать в Delphi2007. Но это нарушало бинарную совместимость с BDS2006. Поэтому было отложено на след. релиз.