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