Замечание
Программа выводит отсчет о точности таймера:
Resolution: 8.39e-07
0 ms. , actual time = 0.024674 seconds.
100 ms. , actual time = 0.127362 seconds.
200 ms. , actual time = 0.222327 seconds.
300 ms. , actual time = 0.314453 seconds.
400 ms. , actual time = 0.393548 seconds.
500 ms. , actual time = 0.465171 seconds.
600 ms. , actual time = 0.630901 seconds.
700 ms. , actual time = 0.738385 seconds.
800 ms. , actual time = 0.775155 seconds.
900 ms. , actual time = 0.836996 seconds.
Эти сообщения показывают, что точность модуля TIMER не слишком высока, однако он может быть полезен для событий, связанных с временем, с точностью приблизительно до одной десятой секунды.
Создание класса измерения производительность
Теперь, когда базовой класс найден и протестирован, следующим шагом будет создание производного от TTimer классу необходим конструктор вместе с функциями-членами для вызова тестируемой функции и сообщения о затраченном времени в заданном числе тестов. В листинге 3.1 приводится один из вариантов создания класса, удовлетворяющего всем вышеперечисленным требованиям, поскольку это всего лишь заголовочный файл. Вы не сможете скомпилировать его.
Листинг 3.1 BENCH.H
(объявление класса TBench)
1: // bench.h – Объявление класса TBench
2:
3: #ifndef__ BENCH_H
4: #define__ BENCH_H 1
// Предотвращение нескольких #include
5:
6: #include <classlib\timer.h>
7:
8: typedef void ( * testfn) (void);
9:
10: class TBench: public TTimer {
11: public;
12: TBench(): TTimer() {}
13: void Benchmark(long numTests, testfn tf);
14: void Report(void);
15: };
16:
17: #endif // __ BENCH_H
Класс TBench выводится из TTimer. Конструктор TBench() (строка 12) вызывает конструктор базового класса TTimer, но не выполняет никаких новых операторов для конструирования объекта TBench. Функция-член Benchmark() (строка 13) имеет два параметра – numTests, равный числу тестов, которые необходимо выполнить, и tf, ссылающийся на тестируемую функцию, которая должна иметь тип void и не должна иметь параметров (см. typedef в строке 8). Вторая функция-член Report(), определенная в строке 14, отображает результат теста.
В листинге 3.2 приводится реализация производного класса TBench. Следующая программа демонстрирует использование этого модуля, поэтому не компилируйте его пока.
Листинг 3.2 BENCH.CPP
(реализация класса TBench)
1: // bench.cpp -- реализация класса TBench
2:
3: #include <stdio.h>
4: #include “bench.h”
5:
6: //вызывает тестируемую функцию tf numTests раз
7: void TBench:: Benchmark(long numTests, testfn tf)
8: {
9: printf(“Running %1d tests…”, numTests);
10: Reset(); // Reset timer to zero
11: Start(); // Start timing
12: While (--numTests >= 0)
13: (* tf) (); // call user test function
14: Stop(); // stop timing
15: puts(“\nTests completed”);
16: }
17:
18: // Выводит результаты теста
19: void TBench::Report(void)
20: {
21: double result = Time();
22: if (result < Resolution())
23: puts(“Results too small for accuracy”);
24: printf(“Elapsed time == %6f sec. \n”, result);
25: }
В строках 7-16 реализуется функция-член Benchmark(). После отображения числа выполняемых тестов, функция сбрасывает и запускает таймер с помощью вызова наследованных функций-членов Reset() и Star().
В строках 12-13 вызывается необходимое число раз тестируемая функция, адрес которой хранится в указателе tf . после завершения последнего теста в строке 14 вызывается еще одна наследованная функция-член Stop(), прерывающая отсчет времени. В строке 15 выводится которое сообщение о том, что тесты завершены.
В строках 19-25 реализуется еще одна функция-член TBench – Report(). В строке 21 переменой result присваивается результат наследованной функции-члена Time() в строках 22-23 выводится сообщение о том, что затраченное время слишком мало для того, чтобы его можно было верно ценить. (если у вас возникло подобное сообщение, рекомендуется увеличить число тестов.) В строке 24 отображаются результаты измерений быстродействия в секундах.
Для того чтобы использовать класс TBench, следует создать объект и передать функции-члену Benchmark() число необходимых для выполнения тестов и адрес тестируемой функции. Затем следует вызвать функцию-член Report() . В листинге 3.3 демонстрируется эта последовательность действий, и он может послужить оболочкой для необходимых вам измерений производительности. После компиляции модулей TBENCH.CPP и BENCH.CPP требуется скомпоновать их с библиотечным файлом TCLASDBS.LIB, содержащим скомпилированный код класса TTimer. Если вы пользуетесь автономным компилятором, добавьте следующие две строки в файл TURBOC.CFG, находящийся в текущем каталоге:
3B-IC:\c 45\in Iude
-LC:\c 45\lic
Затем из командной строки DOS введите следующую команду для компиляции модуля BENCH.CPP и тестовой программы TBENCH.CPP, использующей класс TBench:
c tcen h cen h cidss.lic
В дополнение к заданию имен файлов модулей TBENCH и BENCH предыдущая команда передаст компоновщику имя библиотечного файла BC45 – BIDSS.LIB, в котором содержится скомпилированный код класса TTimer. Второй символ S в BIDSS означает малую (small) модуль памяти, используемую в программах для DOS по умолчанию. (в главе 19приводится более подробное объяснение использования моделей памяти в программировании для DOS и WINDOWS). Как уже отмечалось, класс TTimer, из которого выводится TBENCH, обращается к аппаратным средствам способом, не применимым для WINDOWS. Вы должны скомпилировать эту программу в качестве приложения для DOS.
.
Листинг 3.3. TBENCH.CPP
(тестирование класса TBen h)
1: #include<iostream.h>
2: #include<stdio.h>
3: #include ”cen h.h”
4:
5: #define NUMESTS 20000
6:
7: void Testfn((void);
8:
9: main()
10: {
11: TBen h test;
12:
13: out << “Testing sprintf() fun tion\n”;
14: test.Ben hmark(NUMTESTS. Testfn);
15: test.Report();
16: return 0;
17: }
18:
19: void Testfn(void)
20: {
21: har cuffer[80];
22: doucle d = 3.14159;
23:
24: sprintf(cuffer, “%1f” , d)
25: }
В строке 11 объявляется объект класса TBENCH с именем test. Поскольку С++ вызывает конструктор объекта класса (который вызовет конструктор базового класса Timer), вы можете быть уверены, что объект test соответствующим образом проинициализирован и, следовательно, готов к употреблению. После вывода короткого сообщения программа вызывает функцию-член Benchmark() (строка 14) и передает число необходимых для выполнения тестов, а также адрес тестируемой функции. В строке 15 вызывается функция-член Report() объекта test для вывода результатов тестов. Тестируемая функция (строки 19-25) исключительно для демонстрации вызывать функцию sprintf(). Для проведения другого испытания быстродействия заменить содержимое функции testfn() какими-нибудь другими операторами. Выполнение программы приводит к выводу следующего отсчета:
Testing sprintf() function
Running 20000 tests…
Tests completed
Elapsed time = = 4.118690 sec.