Возможность ускорения работы ArrayCopy

 

ArrayCopy реализована не оптимально, отсюда появляются возможности иногда существенно ускорить ее работу.

Демонстрация:

#property strict

int Benchmark( const bool Flag )
{
  double Dest[];
  double Src[];
  
  ArrayResize(Dest, 1000000);
  ArrayResize(Src, ArraySize(Dest) + 1);
  
  const int PrevTime = GetMicrosecondCount();
  
  if (Flag)
    ArrayFree(Dest); // Ускоряет нижеследующее копирование на ~ 10-20%
    
  // Ошибка в ArrayCopy: крайний входной параметр count == 0 вместо отсутствия действия копирует полностью остаток массива
  ArrayCopy(Dest, Src);
  
  return(GetMicrosecondCount() - PrevTime);
}

void OnStart( void )
{
  int time1 = 0;
  int time2 = 0;
  
  for (int i = 0; i < 100; i++)
  {  
    time1 += Benchmark(TRUE);
    time2 += Benchmark(FALSE);
  }
    
  Print(("time1(") + (string)time1 + " ms.) / time2(" + (string)time2 + " ms.) = " +
        DoubleToString(100.0 * time1 / time2, 2) + "%");
  
  return;
}

Результат выполнения:

time1(361522 ms.) / time2(448436 ms.) = 80.62%

На 20% ArrayCopy выполняется быстрее, если перед ним вызвать соответствующий ArrayFree. Объяснение этому довольно простое: когда ArrayResize > ArraySize, то происходит не просто выделение куска памяти, но и копирование элементов из предыдущего куска в новый. Чтобы избежать явно лишнего иногда переноса данных, целесообразно схлопывать массив-приемник перед копированием в него.

Обратите внимание на ошибку в ArrayCopy - подсвеченный комментарий в коде.
 

 
Спасибо, проверим.
 

Переписали, реализовав ускорение.

0 в ArrayCopy означает WHOLE_ARRAY, так что ошибки нет - копируется все.

 
Renat:

0 в ArrayCopy означает WHOLE_ARRAY, так что ошибки нет - копируется все.

Проверил, действительно, по факту WHOLE_ARRAY нулевой. Тогда явная ошибка в документации. Однако, гораздо удобнее было бы в реализациях многих алгоритмов с копированием, чтобы ноль обозначал отсутствие копирования.
 

Из той же серии возможности ускорения:

#property strict

int Benchmark( const bool Flag )
{
  double Array[];
  
  ArrayResize(Array, 1000000);
  
  const int PrevTime = GetMicrosecondCount();
  
  if (Flag)
    ArrayFree(Array); // Ускоряет нижеследующий resize (ArrayResize > ArraySize) на ~ 5%
    
  ArrayResize(Array, ArraySize(Array) + 1); // ArrayResize > ArraySize
  
  return(GetMicrosecondCount() - PrevTime);
}
/* 
int  ArrayResize(
   void&  array[],                   // массив, переданный по ссылке
   int    new_size,                  // новый размер массива
   int    Amount_Copy = WHOLE_ARRAY, // Количество копируемых элементов (от начала) при ресайзе
   int    reserve_size=0             // резервное значение размера (избыточное)
   );
*/ 

void OnStart( void )
{
  int time1 = 0;
  int time2 = 0;
  
  for (int i = 0; i < 100; i++)
  {  
    time1 += Benchmark(TRUE);
    time2 += Benchmark(FALSE);
  }
    
  Print(("time1(") + (string)time1 + " ms.) / time2(" + (string)time2 + " ms.) = " +
        DoubleToString(100.0 * time1 / time2, 2) + "%");
  
  return;
}

Не хватает оператора присваивания для динамических массивов...

Причина обращения: