В этот раз статья будет очень маленькой, т.к. я просто немного расскажу о том, как используя стандартную библиотеку 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 раз запустим вычисление некоторого факториала:
import std.conv; import std.datetime; import std.datetime.stopwatch; import std.stdio; 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
Конечно, все это прекрасно, но не отменяет использования профайлеров, один из которых встроен прямо в компилятор.
Но об этом, как-нибудь в другой раз…