• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //  loop_time_test.cpp  ----------------------------------------------------------------//
2 
3 //  Copyright Beman Dawes 2013
4 
5 //  Distributed under the Boost Software License, Version 1.0.
6 //  http://www.boost.org/LICENSE_1_0.txt
7 
8 //--------------------------------------------------------------------------------------//
9 
10 //#define BOOST_ENDIAN_NO_INTRINSICS
11 
12 #include <boost/endian/detail/disable_warnings.hpp>
13 
14 #include <boost/endian/conversion.hpp>
15 #include <boost/endian/arithmetic.hpp>
16 #include <boost/cstdint.hpp>
17 #include <boost/timer/timer.hpp>
18 #include <iostream>
19 #include <cstdlib>
20 #include <string>
21 #include <boost/detail/lightweight_main.hpp>
22 
23 #ifdef _MSC_VER
24 #  pragma warning (push)
25 #  pragma warning (disable : 4459)
26 #endif
27 #include <boost/lexical_cast.hpp>
28 #ifdef _MSC_VER
29 #  pragma warning (pop)
30 #endif
31 
32 using namespace boost;
33 using namespace boost::endian;
34 
35 using std::cout;
36 using std::endl;
37 
38 namespace
39 {
40   typedef  boost::timer::nanosecond_type nanosecond_t;
41   std::string command_args;
42   uint64_t n;                 // number of test cases to run
43   int places = 2;             // decimal places for times
44   bool verbose (false);
45   bool time_aligned (true);
46   bool time_unaligned (true);
47   bool time_16(true);
48   bool time_32(true);
49   bool time_64(true);
50 
process_command_line(int argc,char * argv[])51   void process_command_line(int argc, char * argv[])
52   {
53     for (int a = 0; a < argc; ++a)
54     {
55       command_args += argv[a];
56       if (a != argc-1)
57         command_args += ' ';
58     }
59 
60  //   cout << command_args << '\n';;
61 
62     if (argc >=2)
63 #ifndef _MSC_VER
64       n = atoll(argv[1]);
65 #else
66       n = _atoi64(argv[1]);
67 #endif
68 
69     for (; argc > 2; ++argv, --argc)
70     {
71       if ( *(argv[2]+1) == 'p' )
72         places = atoi( argv[2]+2 );
73       else if (*(argv[2] + 1) == 'v')
74         verbose = true;
75       else if (*(argv[2] + 1) == 'a')
76         time_unaligned = false;
77       else if (*(argv[2] + 1) == 'u')
78         time_aligned = false;
79       else if (*(argv[2] + 1) == '1')
80         time_32 = time_64 = false;
81       else if (*(argv[2] + 1) == '3')
82         time_16 = time_64 = false;
83       else if (*(argv[2] + 1) == '6')
84         time_16 = time_32 = false;
85       else
86       {
87         cout << "Error - unknown option: " << argv[2] << "\n\n";
88         argc = -1;
89         break;
90       }
91     }
92 
93     if (argc < 2)
94     {
95       cout << "Usage: loop_time_test n [Options]\n"
96               "  The argument n specifies the number of test cases to run\n"
97               "  Options:\n"
98               "   -v       Verbose messages\n"
99               "   -p#      Decimal places for times; default -p" << places << "\n"
100               "   -a       Aligned tests only\n"
101               "   -u       Unaligned tests only\n"
102               "   -16      16-bit tests only\n"
103               "   -32      32-bit tests only\n"
104               "   -64      64-bit tests only\n"
105               ;
106       return std::exit(1);
107     }
108   }
109 
with_digit_separator(int64_t x)110   std::string with_digit_separator(int64_t x)
111   {
112     std::string s = boost::lexical_cast<std::string>(x);
113     std::string s2;
114 
115     for (std::string::size_type i = 0; i < s.size(); ++i)
116     {
117       if (i && ((s.size()-i) % 3) == 0)
118         s2 += '\'';
119       s2 += s[i];
120     }
121     return s2;
122   }
123 
124 //--------------------------------------------------------------------------------------//
125 
126   template <class T, class EndianT>
time()127   void time()
128   {
129     T total = 0;
130     {
131  //     cout << "*************Endian integer approach...\n";
132       EndianT x(0);
133       boost::timer::cpu_timer t;
134       for (uint64_t i = 0; i < n; ++i)
135       {
136         x += static_cast<T>(i);
137       }
138       t.stop();
139       total += x;
140       cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
141     }
142     {
143 //      cout << "***************Endian conversion approach...\n";
144       T x(0);
145       boost::timer::cpu_timer t;
146       native_to_big_inplace(x);
147       for (uint64_t i = 0; i < n; ++i)
148       {
149         x += static_cast<T>(i);
150       }
151       big_to_native_inplace(x);
152       t.stop();
153       native_to_big_inplace(x);
154       if (x != total)
155         throw std::logic_error("integer approach total != conversion approach total");
156       cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
157     }
158   }
159 
160 
test_big_align_int16()161   void test_big_align_int16()
162   {
163     cout << "<tr><td>16-bit aligned big endian</td>";
164     time<int16_t, big_int16_at>();
165     cout << "</tr>\n";
166   }
167 
test_little_align_int16()168   void test_little_align_int16()
169   {
170     cout << "<tr><td>16-bit aligned little endian</td>";
171     time<int16_t, little_int16_at>();
172     cout << "</tr>\n";
173   }
174 
test_big_int16()175   void test_big_int16()
176   {
177     cout << "<tr><td>16-bit unaligned big endian</td>";
178     time<int16_t, big_int16_t>();
179     cout << "</tr>\n";
180   }
181 
test_little_int16()182   void test_little_int16()
183   {
184     cout << "<tr><td>16-bit unaligned little endian</td>";
185     time<int16_t, little_int16_t>();
186     cout << "</tr>\n";
187   }
188 
test_big_align_int32()189   void test_big_align_int32()
190   {
191     cout << "<tr><td>32-bit aligned big endian</td>";
192     time<int32_t, big_int32_at>();
193     cout << "</tr>\n";
194   }
195 
test_little_align_int32()196   void test_little_align_int32()
197   {
198     cout << "<tr><td>32-bit aligned little endian</td>";
199     time<int32_t, little_int32_at>();
200     cout << "</tr>\n";
201   }
202 
test_big_int32()203   void test_big_int32()
204   {
205     cout << "<tr><td>32-bit unaligned big endian</td>";
206     time<int32_t, big_int32_t>();
207     cout << "</tr>\n";
208   }
209 
test_little_int32()210   void test_little_int32()
211   {
212     cout << "<tr><td>32-bit unaligned little endian</td>";
213     time<int32_t, little_int32_t>();
214     cout << "</tr>\n";
215   }
216 
test_big_align_int64()217   void test_big_align_int64()
218   {
219     cout << "<tr><td>64-bit aligned big endian</td>";
220     time<int64_t, big_int64_at>();
221     cout << "</tr>\n";
222   }
223 
test_little_align_int64()224   void test_little_align_int64()
225   {
226     cout << "<tr><td>64-bit aligned little endian</td>";
227     time<int64_t, little_int64_at>();
228     cout << "</tr>\n";
229   }
230 
test_big_int64()231   void test_big_int64()
232   {
233     cout << "<tr><td>64-bit unaligned big endian</td>";
234     time<int64_t, big_int64_t>();
235     cout << "</tr>\n";
236   }
237 
test_little_int64()238   void test_little_int64()
239   {
240     cout << "<tr><td>64-bit unaligned little endian</td>";
241     time<int64_t, little_int64_t>();
242     cout << "</tr>\n";
243   }
244 
245 }  // unnamed namespace
246 
247 //--------------------------------------------------------------------------------------//
248 
cpp_main(int argc,char * argv[])249 int cpp_main(int argc, char* argv[])
250 {
251   process_command_line(argc, argv);
252 
253   cout
254     << "<html>\n<head>\n<title>Endian Loop Time Test</title>\n</head>\n<body>\n"
255     << "<!-- boost-no-inspect -->\n"
256     << "<div align=\"center\"> <center>\n"
257     << "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\""
258     << "style=\"border-collapse: collapse\" bordercolor=\"#111111\">\n"
259     << "<tr><td colspan=\"6\" align=\"center\"><b>"
260     << BOOST_COMPILER << "</b></td></tr>\n"
261     << "<tr><td colspan=\"6\" align=\"center\"><b>"
262     << " Iterations: " << with_digit_separator(n)
263     << ", Intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG
264     << "</b></td></tr>\n"
265     << "<tr><td><b>Test Case</b></td>\n"
266     "<td align=\"center\"><b>Endian<br>arithmetic<br>type</b></td>\n"
267        "<td align=\"center\"><b>Endian<br>conversion<br>function</b></td>\n"
268        "</tr>\n"
269     ;
270 
271   if (time_aligned)
272   {
273     if (time_16)
274     {
275       test_big_align_int16();
276       test_little_align_int16();
277     }
278     if (time_32)
279     {
280       test_big_align_int32();
281       test_little_align_int32();
282     }
283     if (time_64)
284     {
285       test_big_align_int64();
286       test_little_align_int64();
287     }
288   }
289 
290   if (time_unaligned)
291   {
292     if (time_16)
293     {
294       test_big_int16();
295       test_little_int16();
296     }
297     if (time_32)
298     {
299       test_big_int32();
300       test_little_int32();
301     }
302     if (time_64)
303     {
304       test_big_int64();
305       test_little_int64();
306     }
307   }
308 
309   cout << "\n</div> </center>\n"
310        << "\n</table>\n</body>\n</html>\n";
311 
312   return 0;
313 }
314 
315 #include <boost/endian/detail/disable_warnings_pop.hpp>
316