Присваивание vs Копирование

Посмотрим, насколько эффективнее копировать элементы массива при помощи System.Move, чем присваивать их по одному.

Программа для проверки:

program SpeedTest;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.Classes,
  System.SysUtils,
  System.Diagnostics;

const
  cTestSize  =   10000;
  cArraySize = 1000000;

var
  t : TStopwatch;

function Assignment:integer;
var
  i, j: Integer;
  A,B: array of integer;
begin
  Setlength(A, cArraySize);
  Setlength(B, cArraySize);
  for i := Low(A) to High(A) do
    A[i] := i;

  t := TStopwatch.StartNew;
  for i := 1 to cTestSize do
    for j := Low(A) to High(A) do
      B[j] := A[j];
  t.Stop;

  result := t.ElapsedMilliseconds;
end;

function Copy:integer;
var
  i, j, k: Integer;
  A,B: array of integer;
begin
  Setlength(A,cArraySize);
  Setlength(B,cArraySize);

  for i := Low(A) to High(A) do
    A[i] := i;

  t := TStopwatch.StartNew;
  for i := 1 to cTestSize do
    Move(A[0], B[0], Length(A)*SizeOf(A[0]));
  t.Stop;

  result := t.ElapsedMilliseconds;
end;


begin
  try
      WriteLn('Assignment : ', FormatFloat('0.000', Assignment / 1000));
      WriteLn('Copy       : ', FormatFloat('0.000',       Copy / 1000));
  except
    on e: exception do
      writeln(e.Message);
  end;
  writeln('I''m finished.');
  readln;
end.

Сначала проверим большие массивы, небольшое количество повторов:

const
  cTestSize  =   10000;
  cArraySize = 1000000;

Результат:

Assignment : 34.862
Copy       : 8.638
I'm finished.

Move быстрее в четыре раза.
 

Теперь небольшие массивы, большое количество повторов:

const
  cTestSize  = 10000000;
  cArraySize =     1000;

Замедление более чем в восемь раз:

Assignment : 28.017
Copy       : 3.305
I'm finished.

 

В справке к Move прямо указано:
No range checking is performed.
Попробуем облегчить жизнь массиву и отключим проверку выхода индекса за границы ({$R-}).

На больших массивах наблюдаем ускорение в полтора раза:

Assignment : 13.313
Copy       : 8.834
I'm finished.

На маленьких почти в три раза:

Assignment : 8.923
Copy       : 3.209
I'm finished.

 

Вывод:

Move существенно более быстрый способ копирования элементов массивов. На массивах порядка мегабайта эффект снижается, но всё равно преимущество остаётся разгромным.

Метки: