Чтобы количественно оценить разницу в производительности C-подобного массива и векторов в С++, я написал эту небольшую программу. https://github.com/rajatkhanduja/Benchmarks/blob/master/C%2B%2B/vectorVsArray.cpp
Чтобы сравнить их по общим основаниям, я решил проверить как случайный, так и последовательный доступ. Я добавил итераторы, чтобы просто сравнить их (но это не тот вопрос, на который стоит обратить внимание).
Результаты для 64-разрядной машины Linux с 7,7 ГБ оперативной памяти с размером массива/вектором 1 млн. являются следующими: -
- Время записи в массив.: 12.0378 мс
- Время, затраченное на чтение из массива последовательно.: 2.48413 мс
- Время, затраченное на чтение из массива случайным образом.: 37.3931 мс
- Время, затраченное на запись в динамический массив.: 11.7458 мс
- Время, затраченное на чтение из динамического массива последовательно.: 2.85107 мс
- Время, затраченное на чтение из динамического массива случайным образом.: 36.0579 мс
- Время, затраченное на запись в вектор с использованием индексов.: 11.3909 мс
- Время, затраченное на чтение из вектора с использованием индексов, последовательно.: 4.09106 мс
- Время, затраченное на чтение из вектора с использованием индексов, случайным образом.: 39 мс
- Время, затраченное на запись в вектор, используя итераторы.: 24.9949 мс
- Время считывания с вектора с использованием итераторов.: 18.8049 мс
Размер вектора устанавливается во время инициализации и не изменяется, поэтому нет изменения размера вектора (утверждение в программе помогает проверить это). Времена не включают времена инициализации любого из статически выделенного массива, динамически распределенного массива или вектора.
Согласно статистике, время записи в вектор меньше, чем у массива, но время для чтения из вектора в два раза больше, чем у массива.
Разница довольно маленькая, но есть ли объяснение, почему существует разница в производительности? Что-то не так с тестом? Я ожидал, что оба выйдут с такой же скоростью. Повторение этого теста показывает ту же тенденцию.
Код:
#include <vector>
#include <iostream>
#include <cstdlib>
#include <ctime>
#include <sys/time.h>
#include <cassert>
#define ARR_SIZE 1000000
using std::string;
void printtime (struct timeval& start, struct timeval& end, string str);
int main (void)
{
int arr[ARR_SIZE];
int tmp;
struct timeval start, stop;
srand (time (NULL));
/* Writing data to array */
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
arr[i] = rand();
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to write to array."));
/* Reading data from array */
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = arr[i];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from array sequentially."));
/* Reading data from array randomly*/
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = arr[rand() % ARR_SIZE];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from array randomly."));
int *darr = (int *) calloc (sizeof (int), ARR_SIZE);
/* Writing data to array */
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
darr[i] = rand();
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to write to dynamic array."));
/* Reading data from array */
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = darr[i];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from dynamic array sequentially."));
/* Reading data from dynamic array randomly*/
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = darr[rand() % ARR_SIZE];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from dynamic array randomly."));
std::vector<int> v(ARR_SIZE);
assert (v.capacity() == ARR_SIZE);
/* Writing to vector using indices*/
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
v[i] = rand();
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to write to vector using indices."));
assert (v.capacity() == ARR_SIZE);
/* Reading from vector using indices*/
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = v[i];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from vector using indices, sequentially."));
/* Reading data from dynamic array randomly*/
gettimeofday (&start, NULL);
for (int i = 0; i < ARR_SIZE; i++)
{
tmp = v[rand() % ARR_SIZE];
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from vector using indices, randomly."));
std::vector<int> v2(ARR_SIZE);
/* Writing to vector using iterators*/
gettimeofday (&start, NULL);
std::vector<int>::iterator itr, itr_end;
for (itr = v2.begin(), itr_end = v2.end(); itr != itr_end; itr++)
{
*itr = rand();
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to write to vector using iterators."));
/* Reading from vector using iterators*/
gettimeofday (&start, NULL);
for (itr = v2.begin(), itr_end = v2.end(); itr != itr_end; itr++)
{
tmp = *itr;
}
gettimeofday (&stop, NULL);
printtime (start, stop, string ("Time taken to read from vector using iterators."));
return 0;
}
void printtime (struct timeval& start, struct timeval& end, string str)
{
double start_time, end_time, diff;
start_time = ((start.tv_sec) * 1000 + start.tv_usec/1000.0);
end_time = ((end.tv_sec) * 1000 + end.tv_usec/1000.0);
diff = end_time - start_time;
std::cout << str << " : " << diff << " ms" << std::endl;
}
EDIT
Как указано в комментариях, вот дополнительная информация: -
- Компилятор: - g++ - 4.5.2
- Флаги: - нет (т.е. значения по умолчанию)
- Оптимизация: - Нет (я хотел проверить поведение в обычной настройке. Оптимизация может варьировать поведение программы, например, поскольку переменная tmp никогда не используется, шаг чтения вектора/массива может вообще пропустить или сводится только к последнему назначению. По крайней мере, это то, что я понимаю).