• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  boost run_timer_test.cpp  -----------------------------------------------------//
2 
3 //  Copyright Beman Dawes 2006, 2008
4 //  Copyright 2009 Vicente J. Botet Escriba
5 
6 //  Distributed under the Boost Software License, Version 1.0.
7 //  See http://www.boost.org/LICENSE_1_0.txt
8 
9 //  See http://www.boost.org/libs/chrono for documentation.
10 
11 #include <boost/chrono/process_times.hpp>
12 #include <boost/chrono/timer.hpp>
13 #include <cstdlib> // for atol()
14 #include <iostream>
15 #include <sstream>
16 #include <locale>
17 #include <ctime>
18 #include <cmath>  // for sqrt(), used to burn time
19 
20 using boost::chrono::run_timer;
21 using boost::system::error_code;
22 
23 #include <boost/detail/lightweight_test.hpp>
24 
25 //#define BOOST_TEST(expr) if (!(expr)) std::cout << "*****ERROR*****\n"
26 
27 #define CHECK_REPORT(Timer,String_Stream,R,U,S,Expected_String) \
28   check_report(Timer, String_Stream, R, U, S, Expected_String, __LINE__)
29 
30 
31 namespace
32 {
33   typedef boost::chrono::nanoseconds ns;
34 
check_report(run_timer & tmr,std::stringstream & ss,run_timer::duration r,run_timer::duration u,run_timer::duration s,const std::string & expected,int line)35   bool check_report( run_timer & tmr, std::stringstream & ss,
36     run_timer::duration r, run_timer::duration u, run_timer::duration s,
37     const std::string & expected, int line )
38   {
39     tmr.test_report(r,u,s);
40     bool result(true);
41     if ( ss.str() != expected )
42     {
43       std::cout << "run_timer_test.cpp(" << line << ") : error: actual output \""
44         << ss.str() << "\" != expected \"" << expected << "\"\n";
45       result = false;
46     }
47     return result;
48   }
49 
run_timer_constructor_overload_test()50   void run_timer_constructor_overload_test()
51   {
52     // exercise each supported combination of constructor arguments
53 
54     std::ostream &             os   = std::cout;
55     const int                  pl   = 9;
56     boost::system::error_code  ec;
57 
58     run_timer t1;
59     run_timer t2( os );
60     run_timer t3( ec );
61     run_timer t4( os, ec );
62     run_timer t5( pl );
63     run_timer t6( os, pl );
64     run_timer t7( pl, ec );
65     run_timer t8( os, pl, ec );
66     run_timer t9( "t9, default places,  r %r, c %c, p %p, u %u, s %s\n" );
67     run_timer t10( os, "t10, default places,  r %r, c %c, p %p, u %u, s %s\n" );
68     run_timer t11( "t11, default places,  r %r, c %c, p %p, u %u, s %s\n", ec );
69     run_timer t12( os, "t12, default places,  r %r, c %c, p %p, u %u, s %s\n", ec );
70     run_timer t13( pl, "t13, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n" );
71     run_timer t14( "t14, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", pl );
72     run_timer t15( os, pl, "t15, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n" );
73     run_timer t16( os, "t16, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", pl );
74     run_timer t17( pl, "t17, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", ec );
75     run_timer t18( "t18, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", pl, ec );
76     run_timer t19( os, pl, "t19, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", ec );
77     run_timer t20( os, "t20, explicitly code places,  r %r, c %c, p %p, u %u, s %s\n", pl, ec );
78 
79     std::cout << "Burn some time so run_timers have something to report...";
80     boost::chrono::timer<boost::chrono::high_resolution_clock> t;
81     while ( t.elapsed() < boost::chrono::seconds(1) ) {}
82     std::cout << "\n";
83     std::cout << run_timer::default_places() << " default places\n";
84     std::cout << pl << " explicitly coded places\n";
85   }
86 
87   // accuracy test
accuracy_test(int argc,char * argv[])88   void accuracy_test( int argc, char * argv[] )
89   {
90     long timeout_in_secs = 1;
91     if ( argc > 1 ) timeout_in_secs = std::atol( argv[1] );
92     std::cout << "accuracy test for " << timeout_in_secs << " second(s)...";
93 
94     std::clock_t timeout_in_clock_t = std::clock();
95     timeout_in_clock_t += (timeout_in_secs * CLOCKS_PER_SEC);
96 
97     boost::chrono::system_timer           sys;
98 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
99     boost::chrono::steady_timer        mono;
100 #endif
101     boost::chrono::high_resolution_timer  hires;
102     boost::chrono::process_timer          process;
103 
104     std::clock_t now;
105     do
106     {
107       now = std::clock();
108     } while ( now < timeout_in_clock_t );
109 
110     boost::chrono::system_timer::duration sys_dur = sys.elapsed();
111 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
112     boost::chrono::steady_timer::duration mono_dur = mono.elapsed();
113 #endif
114     boost::chrono::high_resolution_timer::duration hires_dur = hires.elapsed();
115     boost::chrono::process_times times;
116     process.elapsed( times );
117 
118     std::cout << std::endl;
119 
120     ns timeout_in_nanoseconds( static_cast<long long>(timeout_in_secs) * 1000000000LL );
121 
122     //  Allow 20% leeway. Particularly on Linux, there seems to be a large discrepancy
123     //  between std::clock() and higher resolution clocks.
124     ns maximum_delta ( static_cast<long long>(timeout_in_nanoseconds.count() * 0.20 ) );
125 
126     std::cout << timeout_in_nanoseconds.count() << " timeout_in_nanoseconds\n";
127     std::cout << maximum_delta.count() << " maximum_delta\n";
128 
129     std::cout << sys_dur.count() << " sys_dur\n";
130 
131     BOOST_TEST( sys_dur > timeout_in_nanoseconds - maximum_delta
132       && sys_dur < timeout_in_nanoseconds + maximum_delta );
133 
134 #ifdef BOOST_CHRONO_HAS_CLOCK_STEADY
135     std::cout << mono_dur.count() << " mono_dur\n";
136 
137     BOOST_TEST( mono_dur > timeout_in_nanoseconds - maximum_delta
138       && mono_dur < timeout_in_nanoseconds + maximum_delta );
139 #endif
140 
141     std::cout << hires_dur.count() << " hires_dur\n";
142 
143     BOOST_TEST( hires_dur > timeout_in_nanoseconds - maximum_delta
144       && hires_dur < timeout_in_nanoseconds + maximum_delta );
145 
146     std::cout << times.real.count() << " times.real\n";
147 
148     BOOST_TEST( times.real > timeout_in_nanoseconds - maximum_delta
149       && times.real < timeout_in_nanoseconds + maximum_delta );
150   }
151 
152   //  report test
153 
report_test()154   void report_test()
155   {
156     {
157       std::stringstream ss;
158       run_timer t(ss);
159       BOOST_TEST( CHECK_REPORT(t, ss, ns(0), ns(0), ns(0),
160         "\nreal 0.000s, cpu 0.000s (0.0%), user 0.000s, system 0.000s\n" ) );
161     }
162 
163     {
164       std::stringstream ss;
165       run_timer t(ss);
166       BOOST_TEST( CHECK_REPORT(t, ss, ns(3000000000LL), ns(2000000000LL), ns(1000000000LL),
167         "\nreal 3.000s, cpu 3.000s (100.0%), user 2.000s, system 1.000s\n" ) );
168     }
169 
170     {
171       std::stringstream ss;
172       run_timer t( ss, "9 places: r %r, c %c, p %p, u %u, s %s", 9 );
173       BOOST_TEST( CHECK_REPORT(t, ss, ns(3000000003LL), ns(2000000002LL), ns(1000000001LL),
174         "9 places: "
175         "r 3.000000003, c 3.000000003, p 100.0, u 2.000000002, s 1.000000001" ) );
176     }
177   }
178 
179   //  process_timer_test
180 
process_timer_test()181   void process_timer_test()
182   {
183     std::cout << "process_timer_test..." << std::flush;
184 
185     boost::chrono::process_timer t;
186     double res=0; // avoids optimization
187     for (long i = 0; i < 10000000L; ++i)
188     {
189       res+=std::sqrt( static_cast<double>(i) ); // avoids optimization
190     }
191 
192     boost::chrono::process_times times;
193     times.real = times.system = times.user = ns(0);
194 
195     BOOST_TEST( times.real == ns(0) );
196     BOOST_TEST( times.user == ns(0) );
197     BOOST_TEST( times.system == ns(0) );
198 
199     t.elapsed( times );
200     std::cout << "\n";
201 
202     std::cout << times.real.count() << " times.real\n";
203     std::cout << times.user.count() << " times.user\n";
204     std::cout << times.system.count() << " times.system\n";
205     std::cout << (times.user+times.system).count() << " times.user+system\n";
206     BOOST_TEST( times.real > ns(1) );
207 
208     BOOST_TEST( times.user+times.system  > ns(1) );
209 
210     std::cout << "complete " << res << std::endl;
211   }
212 }
213 
main(int argc,char * argv[])214 int main( int argc, char * argv[] )
215 {
216   std::locale loc( "" );     // test with appropriate locale
217   std::cout.imbue( loc );
218 
219   accuracy_test( argc, argv );
220   run_timer_constructor_overload_test();
221   process_timer_test();
222   report_test();
223 
224   return boost::report_errors();
225 }
226 
227