Почему std:: unique_ptr намного медленнее стандартного указателя... до оптимизации

EDIT: Извлеченный урок, всегда используйте оптимизацию при выполнении тестов...

Я решил посмотреть std::unique_ptr в качестве альтернативы моей программе, причины чего не важны.

РЕДАКТИРОВАТЬ: После использования оптимизаций компилятора они, похоже, принимают эквивалентные количества времени.

Как я протестировал:

time_t current_time;
time(&current_time);
srand((int)current_time);
//int* p0 = new int[NUM_TESTS];
//int* p1 = new int[NUM_TESTS];
std::unique_ptr<int[]> u_p0{ new int[NUM_TESTS] };
std::unique_ptr<int[]> u_p1{ new int[NUM_TESTS] };
for (unsigned i = 0; i < NUM_TESTS; ++i){
    u_p0[i] = rand(); // use p0 and p1 for the standard ptr test
    u_p1[i] = rand();
}
int result;
auto start = std::chrono::steady_clock::now();
for (unsigned index = 0; index < NUM_TESTS; ++index){
    result = u_p0[index] + u_p1[index]; // use p0 and p1 for standard ptr test
}
auto end = std::chrono::steady_clock::now();
double duration = std::chrono::duration_cast<std::chrono::duration<double>>(end - start).count();
printf("time: %f\n", duration);

Моя среда:

  • Windows 8.1 64bit
  • MSVC-компилятор в VS2013 EDIT: использование Release
  • Intel 4790k (стандартные часы)
  • ОЗУ 1600 МГц.

Мои результаты (EDITED: использование оптимизированной компиляции):

// NUM_TESTS = 1,000,000

/*
STD:
    0.001005
    0.001001
    0.001000
    0.001000
    0.001015
*/
/*
unique_ptr:
    0.001000
    0.001000
    0.000997
    0.001000
    0.001017
*/

Ответ 1

Потому что "стандартные флаги компилятора" означает, что вы компилируете без включенной оптимизации.

std::unique_ptr - это тонкая оболочка вокруг необработанного указателя. Таким образом, при разыменовании его он проходит через очень простую функцию пересылки, которую компилятор может оптимизировать. Но это только делает, если оптимизация включена. Если они есть, то это может устранить накладные расходы, проходящие через оболочку, поэтому производительность будет такой же, как если бы вы использовали только необработанный указатель.

Но если вы не попросите компилятор оптимизировать ваш код, то каждый раз, когда вы обращаетесь к указателю, он должен пройти через небольшую функцию обертки, чтобы перейти к фактическому внутреннему указателю.

Всегда, всегда включайте оптимизацию при бенчмаркинге.