[fpc-devel] CompareMem slower in FPC 2.4.4

José Mejuto joshyfun at gmail.com
Thu Jun 2 18:45:23 CEST 2011


Hello FPC,

Wednesday, June 1, 2011, 10:07:18 PM, you wrote:

MK> In my tests, FPC 2.4.4 has much slower CompareMem than FPC 2.4.2, at
MK> least for some cases:

The difference is that CompareMem takes the same time to check a
memory block if the elements are equal or different, while the pascal
code aborts inmediatly after first difference.

I had performed a fast test filling 2 megabytes of memory, the first
with value "1" and the second with value "2". Performing the test 10
millions times takes 610 milliseconds. In the second test fill both
arrays with same value, and CompareMem takes 610 milliseconds.

After some tests (not very professional) CompareMem takes much more
advantage if the amount of bytes to be compared are more than 32-38, so
the best performance I get is using this function:

function XCompareByte(const p1,p2,Length: sizeInt): SizeInt;
var
  j: SizeInt;
  PB1: PBYTE absolute p1;
  PB2: PBYTE absolute p2;
begin
  if Length<=38 then begin
    for j := 0 to Length-1 do begin
      if pb1[j]<>PB2[j] then begin
        Result:=BYTE(PB1[j]-PB2[j]);
        exit;
      end;
    end;
    Result:=0;
  end else begin
    Result:=CompareByte(p1,p2,Length);
  end;
end;

In my computer Intel 9300 QCore WindowsXP this function get the best
of the two worlds, fast comparison escape for different memory blocks,
fast compare for small blocks and the "rep cmpsl" for larger blocks,
performance that can not be achieved with the pascal loop. The
comparison penalty if rapidly payed with the fast escape in case of
differeces in the very first bytes.

I'm quite sure the magic number is 32 not 38, but in my case I get
better performance with 38.

Simple test code:

procedure Comparememtest;
const
  COMPARELENGTH=1000;
var
  p1,p2: PBYTE;
  j: integer;
  ST,ET: TTimeStamp;
begin
  GetMem(p1,1000000);
  for j := 0 to 1000000-1 do begin
    p1[j]:=0;
  end;
  GetMem(p2,1000000);
  for j := 0 to 1000000-1 do begin
    p2[j]:=0;
  end;
  ST:=DateTimeToTimeStamp(Now);
  for j := 0 to 10000000 do begin
    XCompareByte(SizeInt(p1),SizeInt(p2),COMPARELENGTH);
  end;
  ET:=DateTimeToTimeStamp(Now);
  self.Caption:=inttostr(ET.Time-ST.Time);
  FreeMem(p1);
  FreeMem(p2);
end;

Times table:
                             PlainCompare  CompareByte    XCompareByte
                             ------------  -----------    ------------
Equal arrays 1000 elements   16250 ms      625 ms         656 ms
Diff. arrays 1000 elements      62 ms      640 ms         656 ms

Equal arrays 32 elements       547 ms      625 ms         547 ms
Diff. arrays 32 elements        62 ms      640 ms          62 ms

-- 
Best regards,
 José




More information about the fpc-devel mailing list