Измерение времени выполнения отдельных фрагментов кода

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

Возьмем, к примеру, всем надоевшую функцию итеративно вычисляющую факториал:

int factorial(int N)
{
	auto P = 1;

	for (int i = 1; i < N; i++)
	{
		P *= i;
	}

	return P;
}

И попробуем, на нескольких ее прогонах, посмотреть сколько времени может выполняться эта маленькая, но иногда очень полезная функция. Для этого, воспользуемся интересным шаблоном benchmark, который в качестве аргументов ряд параметров времени компиляции, в роли которых выступает набор тестируемых процедур; а в качестве аргументов времени выполнения, шаблон принимает единственный параметр — количество попыток исполнения функции:

benchmark!(f0, f1, ...fn)(N);

А теперь проведем небольшой эксперимент, но перед этим обернем факториал в функцию void:

void testFactorial()
{
	factorial(15);
}

Теперь собственно эксперимент, в котором мы 10 000 раз запустим вычисление некоторого факториала:

auto r = benchmark!(testFactorial, testFactorial)(10_000);
writeln("1st test: ", r[0].nsecs);
writeln("2nd test: ", to!Duration(r[1]));

Небольшое пояснение: benchmark возвращает кортеж типов, состоящий из объектов типа TimeDuration, который для наших целей мало информативен, а потому мы переводим его во что-нибудь более полезное, например, как в первом случае, в наносекунды. Дело в том, что в стандартной библиотеке определено несколько псевдонимов на основные единицы времени: миллисекунды, секунды, микросекунды и т.д., которые доступны в виде английских сокращений (они широко известны, а если вы их не знаете, то любой учебник английского или мануал по стандартной библиотеке все объяснит).
Второй пример переводит один из элементов кортежа в тип Duration, который выводит информацию более детально, автоматически вырезая ненужное.

Результат примерно такой:

E:\Projects>fact
1st test: 2262926
2nd test: 2 ms, 247 µs, and 8 hnsecs

Конечно, все это прекрасно, но не отменяет использования профайлеров, один из которых встроен прямо в компилятор. Но об этом, как-нибудь в другой раз…

Добавить комментарий