Тестирование производительности участка кода. Оценка производительности алгоритма
Иногда бывает необходимость протестировать алгоритм или часть кода, чтоб узнать "не здесь ли тормозит?". А использование профайлера слишком монструозно или не практично. Тогда можно замерить производительность участка кода, прямо в коде. Для этого есть много методов, и все они не без погрешностей. [spoiler] Чем могут быть вызваны погрешности? Операционные системы многозадачны, и чаще имеют архитектору вытесняющей многозадачности по приоритетам. Система может отдать процессорное время другому процессу, а не нашему тестируемому. Также приложение вовремя вызова системных сервисов может находится в режиме ядра, и это тоже влияет на результат замера. Также сам метод имеет определенную точность, и погрешность.=)
Поэтому для большой точности замера, поставьте приоритет реального времени Вашему процессу, но это может решить лишь проблему с вытеснением другим процессом. Для решение проблем с режимами нужно использовать другие методы, такие например как GetSystemTime для Windows, но у нее большие погрешности во времени замера.
Следует, также "прогнать" замеры несколько раз, взять средний результат, так, как погрешности все равно будут и от них никуда не деться.=)
И так самими методы:
/*http://esate.ru, Flashhell*/
#include <vector> // STL массив - vector
#include <iostream> // ввод, вывод
#include <algorithm> // для функции перемешивания random_shuffle, но там есть еще много вкусностей=)
using namespace std;
// для работы подсчета тактов Windows - 1) МЕТОД
#include <intrin.h>
#pragma intrinsic(__rdtsc)
//------------------------------------------------
// стандартные для C функции и структуры работы со временем - 2) МЕТОД
#include <time.h>
//------------------------------------------------
// 3) МЕТОД и 4 МЕТОД
#include <windows.h>
//------------------------------------------------
// тестируемый алгоритм, если можно его так назвать =)
void test_algorithm();
//! Метод подсчета тактов процессора(Windows) - 1) МЕТОД
unsigned __int64 tick()
{
return (__rdtsc());
}
//! ifdef макрос определяющий OS LInux на gcc - 1) МЕТОД
#ifdef __linux__
//! Метод подсчета тактов процессора(Linux)
static inline unsigned long long int tick()
{
unsigned long long int d;
__asm__ __volatile__ ("rdtsc" : "=A" (d) );
return d;
}
#endif
int main()
{
// 1) Метод
unsigned long long int a = 0;
unsigned long long int b = 0;
a=tick();
test_algorithm();
b=tick();
cout<<"1) Method "<<b-a<<"\n";
// 2) Метод
clock_t time;
time = clock();
test_algorithm();
time = clock() - time;
cout <<"2) Method "<<time<<"\n";
cout <<"2) Method time in seconds "<<(double)time / CLOCKS_PER_SEC<<"\n";
// 3) Метод
double start = GetTickCount();
test_algorithm();
double finish = GetTickCount();
cout <<"3) Method "<<finish - start<<"\n";
cout <<"3) Method time in seconds "<<(double)(finish - start) / CLOCKS_PER_SEC<<"\n"; //CLOCKS_PER_SEC объявлен в time.h
// 4) Метод
LARGE_INTEGER freq;
QueryPerformanceFrequency(&freq);
LARGE_INTEGER time1;
QueryPerformanceCounter(&time1);
test_algorithm();
LARGE_INTEGER time2;
QueryPerformanceCounter(&time2);
time2.QuadPart -= time1.QuadPart;
double span = (double) time2.QuadPart / freq.QuadPart;
cout <<"4) Method time in seconds "<<span<<"\n";
return 0;
}
//! Тестируемый алгоритм, сейчас представляет лишь цикл забивки вектора и его перемешивание
void test_algorithm()
{
vector <int> vec;
int i = 0;
while(i < 100000)
{
vec.push_back(i);
i++;
}
random_shuffle(vec.begin(), vec.end());
}
Сразу прошу не обижаться, на большое количество комментов в коде, я посчитал, что так лучше ИМХО)))
PS Все представленные здесь методы так или иначе завязаны на тактах процессора. Если Вам нужно протестить много кода, лучше задумать об использовании профайлера, к примеру codeanalyst