1 // speed_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 "speed_test_functions.hpp"
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 <boost/detail/lightweight_main.hpp>
22
23 using namespace boost;
24 using namespace boost::endian;
25
26 using std::cout;
27 using std::endl;
28
29 namespace
30 {
31 typedef boost::timer::nanosecond_type nanosecond_t;
32 std::string command_args;
33 uint64_t n; // number of test cases to run
34 int places = 2; // decimal places for times
35 bool verbose (false);
36
process_command_line(int argc,char * argv[])37 void process_command_line(int argc, char * argv[])
38 {
39 for (int a = 0; a < argc; ++a)
40 {
41 command_args += argv[a];
42 if (a != argc-1)
43 command_args += ' ';
44 }
45
46 // cout << command_args << '\n';;
47
48 if (argc >=2)
49 #ifndef _MSC_VER
50 n = atoll(argv[1]);
51 #else
52 n = _atoi64(argv[1]);
53 #endif
54
55 for (; argc > 2; ++argv, --argc)
56 {
57 if ( *(argv[2]+1) == 'p' )
58 places = atoi( argv[2]+2 );
59 else if ( *(argv[2]+1) == 'v' )
60 verbose = true;
61 else
62 {
63 cout << "Error - unknown option: " << argv[2] << "\n\n";
64 argc = -1;
65 break;
66 }
67 }
68
69 if (argc < 2)
70 {
71 cout << "Usage: speed_test n [Options]\n"
72 " The argument n specifies the number of test cases to run\n"
73 " Options:\n"
74 " -v Verbose messages\n"
75 " -p# Decimal places for times; default -p" << places << "\n";
76 return std::exit(1);
77 }
78 }
79
80 //--------------------------------------------------------------------------------------//
81
82 template <class T, class EndianT, class Function>
time(Function f)83 void time(Function f)
84 {
85 T x(0);
86 EndianT y(0);
87 boost::timer::cpu_timer t;
88 for (uint64_t i = 0; i < n; ++i)
89 {
90 f(x, y);
91 }
92 t.stop();
93 cout << "<td align=\"right\">" << t.format(places, "%t") << " s</td>";
94 }
95
test_big_int16()96 void test_big_int16()
97 {
98 cout << "<tr><td>16-bit aligned big endian</td>";
99 time<int16_t, big_int16_t>(user::return_x_big_int16);
100 time<int16_t, big_int16_t>(user::return_x_value_big_int16);
101 time<int16_t, big_int16_t>(user::return_x_inplace_big_int16);
102 time<int16_t, big_int16_t>(user::return_y_big_int16);
103 cout << "</tr>\n";
104 }
105
test_little_int16()106 void test_little_int16()
107 {
108 cout << "<tr><td>16-bit aligned little endian</td>";
109 time<int16_t, little_int16_t>(user::return_x_little_int16);
110 time<int16_t, little_int16_t>(user::return_x_value_little_int16);
111 time<int16_t, little_int16_t>(user::return_x_inplace_little_int16);
112 time<int16_t, little_int16_t>(user::return_y_little_int16);
113 cout << "</tr>\n";
114 }
115
test_big_int32()116 void test_big_int32()
117 {
118 cout << "<tr><td>32-bit aligned big endian</td>";
119 time<int32_t, big_int32_t>(user::return_x_big_int32);
120 time<int32_t, big_int32_t>(user::return_x_value_big_int32);
121 time<int32_t, big_int32_t>(user::return_x_inplace_big_int32);
122 time<int32_t, big_int32_t>(user::return_y_big_int32);
123 cout << "</tr>\n";
124 }
125
test_little_int32()126 void test_little_int32()
127 {
128 cout << "<tr><td>32-bit aligned little endian</td>";
129 time<int32_t, little_int32_t>(user::return_x_little_int32);
130 time<int32_t, little_int32_t>(user::return_x_value_little_int32);
131 time<int32_t, little_int32_t>(user::return_x_inplace_little_int32);
132 time<int32_t, little_int32_t>(user::return_y_little_int32);
133 cout << "</tr>\n";
134 }
135
test_big_int64()136 void test_big_int64()
137 {
138 cout << "<tr><td>64-bit aligned big endian</td>";
139 time<int64_t, big_int64_t>(user::return_x_big_int64);
140 time<int64_t, big_int64_t>(user::return_x_value_big_int64);
141 time<int64_t, big_int64_t>(user::return_x_inplace_big_int64);
142 time<int64_t, big_int64_t>(user::return_y_big_int64);
143 cout << "</tr>\n";
144 }
145
test_little_int64()146 void test_little_int64()
147 {
148 cout << "<tr><td>64-bit aligned little endian</td>";
149 time<int64_t, little_int64_t>(user::return_x_little_int64);
150 time<int64_t, little_int64_t>(user::return_x_value_little_int64);
151 time<int64_t, little_int64_t>(user::return_x_inplace_little_int64);
152 time<int64_t, little_int64_t>(user::return_y_little_int64);
153 cout << "</tr>\n";
154 }
155
156 } // unnamed namespace
157
158 //--------------------------------------------------------------------------------------//
159
cpp_main(int argc,char * argv[])160 int cpp_main(int argc, char* argv[])
161 {
162 process_command_line(argc, argv);
163
164 cout
165 << "<html>\n<head>\n<title>Endian Speed Test</title>\n</head>\n<body>\n"
166 << "<table border=\"1\" cellpadding=\"5\" cellspacing=\"0\""
167 << "style=\"border-collapse: collapse\" bordercolor=\"#111111\">\n"
168 << "<tr><td colspan=\"6\" align=\"center\"><b>"
169 << BOOST_COMPILER << "</b></td></tr>\n"
170 << "<tr><td colspan=\"6\" align=\"center\"><b>"
171 << " Iterations: " << n
172 << ", Intrinsics: " BOOST_ENDIAN_INTRINSIC_MSG
173 << "</b></td></tr>\n"
174 << "<tr><td><b>Test Case</b></td>\n"
175 "<td align=\"center\"><b>int<br>arg</b></td>\n"
176 "<td align=\"center\"><b>int<br>value(arg)</b></td>\n"
177 "<td align=\"center\"><b>int<br>in place(arg)</b></td>\n"
178 "<td align=\"center\"><b>Endian<br>arg</b></td>\n"
179 "</tr>\n"
180 ;
181
182 test_big_int16();
183 test_little_int16();
184 test_big_int32();
185 test_little_int32();
186 test_big_int64();
187 test_little_int64();
188
189 cout << "\n</table>\n</body>\n</html>\n";
190
191 return 0;
192 }
193
194 #include <boost/endian/detail/disable_warnings_pop.hpp>
195