]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/libs/lexical_cast/perf/performance_test.cpp
update ceph source to reef 18.1.2
[ceph.git] / ceph / src / boost / libs / lexical_cast / perf / performance_test.cpp
1 // (C) Copyright Antony Polukhin, 2012-2022.
2 // Use, modification and distribution are subject to the
3 // Boost Software License, Version 1.0. (See accompanying file
4 // LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
5
6 // See http://www.boost.org/libs/config for most recent version.
7
8 //
9 // Testing lexical_cast<> performance
10 //
11
12 #define BOOST_ERROR_CODE_HEADER_ONLY
13 #define BOOST_CHRONO_HEADER_ONLY
14
15 #include <boost/lexical_cast.hpp>
16
17 #include <boost/chrono.hpp>
18 #include <fstream>
19 #include <cstring>
20 #include <boost/container/string.hpp>
21
22 // File to output data
23 std::fstream fout;
24
25 namespace boost {
26 inline std::istream& operator>> (std::istream& in, boost::array<char,50>& res) {
27 in >> res.begin();
28 return in;
29 }
30 }
31
32 template <class OutT, class InT>
33 static inline void test_lexical(const InT& in_val) {
34 OutT out_val = boost::lexical_cast<OutT>(in_val);
35 (void)out_val;
36 }
37
38 template <class OutT, class InT>
39 static inline void test_ss_constr(const InT& in_val) {
40 OutT out_val;
41 std::stringstream ss;
42 ss << in_val;
43 if (ss.fail()) throw std::logic_error("descr");
44 ss >> out_val;
45 if (ss.fail()) throw std::logic_error("descr");
46 }
47
48 template <class OutT, class CharT, std::size_t N>
49 static inline void test_ss_constr(const boost::array<CharT, N>& in_val) {
50 OutT out_val;
51 std::stringstream ss;
52 ss << in_val.begin();
53 if (ss.fail()) throw std::logic_error("descr");
54 ss >> out_val;
55 if (ss.fail()) throw std::logic_error("descr");
56 }
57
58 template <class OutT, class StringStreamT, class CharT, std::size_t N>
59 static inline void test_ss_noconstr(StringStreamT& ss, const boost::array<CharT, N>& in_val) {
60 OutT out_val;
61 ss << in_val.begin(); // ss is an instance of std::stringstream
62 if (ss.fail()) throw std::logic_error("descr");
63 ss >> out_val;
64 if (ss.fail()) throw std::logic_error("descr");
65 /* reseting std::stringstream to use it again */
66 ss.str(std::string());
67 ss.clear();
68 }
69
70 template <class OutT, class StringStreamT, class InT>
71 static inline void test_ss_noconstr(StringStreamT& ss, const InT& in_val) {
72 OutT out_val;
73 ss << in_val; // ss is an instance of std::stringstream
74 if (ss.fail()) throw std::logic_error("descr");
75 ss >> out_val;
76 if (ss.fail()) throw std::logic_error("descr");
77 /* reseting std::stringstream to use it again */
78 ss.str(std::string());
79 ss.clear();
80 }
81
82 struct structure_sprintf {
83 template <class OutT, class BufferT, class InT>
84 static inline void test(BufferT* buffer, const InT& in_val, const char* const conv) {
85 sprintf(buffer, conv, in_val);
86 OutT out_val(buffer);
87 }
88
89 template <class OutT, class BufferT>
90 static inline void test(BufferT* buffer, const std::string& in_val, const char* const conv) {
91 sprintf(buffer, conv, in_val.c_str());
92 OutT out_val(buffer);
93 }
94 };
95
96 struct structure_sscanf {
97 template <class OutT, class BufferT, class CharT, std::size_t N>
98 static inline void test(BufferT* /*buffer*/, const boost::array<CharT, N>& in_val, const char* const conv) {
99 OutT out_val;
100 sscanf(in_val.cbegin(), conv, &out_val);
101 }
102
103 template <class OutT, class BufferT, class InT>
104 static inline void test(BufferT* /*buffer*/, const InT& in_val, const char* const conv) {
105 OutT out_val;
106 sscanf(reinterpret_cast<const char*>(in_val), conv, &out_val);
107 }
108
109 template <class OutT, class BufferT>
110 static inline void test(BufferT* /*buffer*/, const std::string& in_val, const char* const conv) {
111 OutT out_val;
112 sscanf(in_val.c_str(), conv, &out_val);
113 }
114
115 template <class OutT, class BufferT>
116 static inline void test(BufferT* /*buffer*/, const boost::iterator_range<const char*>& in_val, const char* const conv) {
117 OutT out_val;
118 sscanf(in_val.begin(), conv, &out_val);
119 }
120 };
121
122 struct structure_fake {
123 template <class OutT, class BufferT, class InT>
124 static inline void test(BufferT* /*buffer*/, const InT& /*in_val*/, const char* const /*conv*/) {}
125 };
126
127 static const int fake_test_value = 9999;
128
129 template <class T>
130 static inline void min_fancy_output(T v1, T v2, T v3, T v4) {
131 const char beg_mark[] = "!!! *";
132 const char end_mark[] = "* !!!";
133 const char no_mark[] = "";
134
135 unsigned int res = 4;
136 if (v1 < v2 && v1 < v3 && v1 < v4) res = 1;
137 if (v2 < v1 && v2 < v3 && v2 < v4) res = 2;
138 if (v3 < v1 && v3 < v2 && v3 < v4) res = 3;
139
140 fout << "[ "
141 << (res == 1 ? beg_mark : no_mark)
142 ;
143
144 if (v1) fout << v1;
145 else fout << "<1";
146
147 fout << (res == 1 ? end_mark : no_mark)
148 << " ][ "
149 << (res == 2 ? beg_mark : no_mark)
150 ;
151
152 if (v2) fout << v2;
153 else fout << "<1";
154
155 fout << (res == 2 ? end_mark : no_mark)
156 << " ][ "
157 << (res == 3 ? beg_mark : no_mark)
158 ;
159
160 if (v3) fout << v3;
161 else fout << "<1";
162
163 fout << (res == 3 ? end_mark : no_mark)
164 << " ][ "
165 << (res == 4 ? beg_mark : no_mark)
166 ;
167
168 if (!v4) fout << "<1";
169 else if (v4 == fake_test_value) fout << "---";
170 else fout << v4;
171
172 fout
173 << (res == 4 ? end_mark : no_mark)
174 << " ]";
175 }
176
177 template <unsigned int IetartionsCountV, class ToT, class SprintfT, class FromT>
178 static inline void perf_test_impl(const FromT& in_val, const char* const conv) {
179
180 typedef boost::chrono::steady_clock test_clock;
181 test_clock::time_point start;
182 typedef boost::chrono::milliseconds duration_t;
183 duration_t lexical_cast_time, ss_constr_time, ss_noconstr_time, printf_time;
184
185 start = test_clock::now();
186 for (unsigned int i = 0; i < IetartionsCountV; ++i) {
187 test_lexical<ToT>(in_val);
188 test_lexical<ToT>(in_val);
189 test_lexical<ToT>(in_val);
190 test_lexical<ToT>(in_val);
191 }
192 lexical_cast_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
193
194
195 start = test_clock::now();
196 for (unsigned int i = 0; i < IetartionsCountV; ++i) {
197 test_ss_constr<ToT>(in_val);
198 test_ss_constr<ToT>(in_val);
199 test_ss_constr<ToT>(in_val);
200 test_ss_constr<ToT>(in_val);
201 }
202 ss_constr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
203
204 std::stringstream ss;
205 start = test_clock::now();
206 for (unsigned int i = 0; i < IetartionsCountV; ++i) {
207 test_ss_noconstr<ToT>(ss, in_val);
208 test_ss_noconstr<ToT>(ss, in_val);
209 test_ss_noconstr<ToT>(ss, in_val);
210 test_ss_noconstr<ToT>(ss, in_val);
211 }
212 ss_noconstr_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
213
214
215 char buffer[128];
216 start = test_clock::now();
217 for (unsigned int i = 0; i < IetartionsCountV; ++i) {
218 SprintfT::template test<ToT>(buffer, in_val, conv);
219 SprintfT::template test<ToT>(buffer, in_val, conv);
220 SprintfT::template test<ToT>(buffer, in_val, conv);
221 SprintfT::template test<ToT>(buffer, in_val, conv);
222 }
223 printf_time = boost::chrono::duration_cast<duration_t>(test_clock::now() - start);
224
225 min_fancy_output(
226 lexical_cast_time.count(),
227 ss_constr_time.count(),
228 ss_noconstr_time.count(),
229 boost::is_same<SprintfT, structure_fake>::value ? fake_test_value : printf_time.count()
230 );
231 }
232
233 template <class ToT, class SprintfT, class FromT>
234 static inline void perf_test(const std::string& test_name, const FromT& in_val, const char* const conv) {
235 const unsigned int ITERATIONSCOUNT = 100000;
236 fout << " [[ " << test_name << " ]";
237
238 perf_test_impl<ITERATIONSCOUNT/4, ToT, SprintfT>(in_val, conv);
239
240 fout << "]\n";
241 }
242
243
244 template <class ConverterT>
245 void string_like_test_set(const std::string& from) {
246 typedef structure_sscanf ssc_t;
247 ConverterT conv;
248
249 perf_test<char, ssc_t>(from + "->char", conv("c"), "%c");
250 perf_test<signed char, ssc_t>(from + "->signed char", conv("c"), "%hhd");
251 perf_test<unsigned char, ssc_t>(from + "->unsigned char", conv("c"), "%hhu");
252
253 perf_test<int, ssc_t>(from + "->int", conv("100"), "%d");
254 perf_test<short, ssc_t>(from + "->short", conv("100"), "%hd");
255 perf_test<long int, ssc_t>(from + "->long int", conv("100"), "%ld");
256 perf_test<boost::long_long_type, ssc_t>(from + "->long long", conv("100"), "%lld");
257
258 perf_test<unsigned int, ssc_t>(from + "->unsigned int", conv("100"), "%u");
259 perf_test<unsigned short, ssc_t>(from + "->unsigned short", conv("100"), "%hu");
260 perf_test<unsigned long int, ssc_t>(from + "->unsigned long int", conv("100"), "%lu");
261 perf_test<boost::ulong_long_type, ssc_t>(from + "->unsigned long long", conv("100"), "%llu");
262
263 // perf_test<bool, ssc_t>(from + "->bool", conv("1"), "%");
264
265 perf_test<float, ssc_t>(from + "->float", conv("1.123"), "%f");
266 perf_test<double, ssc_t>(from + "->double", conv("1.123"), "%lf");
267 perf_test<long double, ssc_t>(from + "->long double", conv("1.123"), "%Lf");
268 perf_test<boost::array<char, 50>, ssc_t>(from + "->array<char, 50>", conv("1.123"), "%s");
269
270 perf_test<std::string, structure_fake>(from + "->string", conv("string"), "%Lf");
271 perf_test<boost::container::string, structure_fake>(from + "->container::string"
272 , conv("string"), "%Lf");
273
274 }
275
276 struct to_string_conv {
277 std::string operator()(const char* const c) const {
278 return c;
279 }
280 };
281
282 struct to_char_conv {
283 const char* operator()(const char* const c) const {
284 return c;
285 }
286 };
287
288 struct to_uchar_conv {
289 const unsigned char* operator()(const char* const c) const {
290 return reinterpret_cast<const unsigned char*>(c);
291 }
292 };
293
294
295 struct to_schar_conv {
296 const signed char* operator()(const char* const c) const {
297 return reinterpret_cast<const signed char*>(c);
298 }
299 };
300
301 struct to_iterator_range {
302 boost::iterator_range<const char*> operator()(const char* const c) const {
303 return boost::make_iterator_range(c, c + std::strlen(c));
304 }
305 };
306
307 struct to_array_50 {
308 boost::array<char, 50> operator()(const char* const c) const {
309 boost::array<char, 50> ret;
310 std::strcpy(ret.begin(), c);
311 return ret;
312 }
313 };
314
315 int main(int argc, char** argv) {
316 BOOST_ASSERT(argc >= 2);
317 std::string output_path(argv[1]);
318 output_path += "/results.txt";
319 fout.open(output_path.c_str(), std::fstream::in | std::fstream::out | std::fstream::app);
320 BOOST_ASSERT(fout);
321
322 fout << "[section " << BOOST_COMPILER << "]\n"
323 << "[table:id Performance Table ( "<< BOOST_COMPILER << ")\n"
324 << "[[From->To] [lexical_cast] [std::stringstream with construction] "
325 << "[std::stringstream without construction][scanf/printf]]\n";
326
327
328 // From std::string to ...
329 string_like_test_set<to_string_conv>("string");
330
331 // From ... to std::string
332 perf_test<std::string, structure_sprintf>("string->char", 'c', "%c");
333 perf_test<std::string, structure_sprintf>("string->signed char", static_cast<signed char>('c'), "%hhd");
334 perf_test<std::string, structure_sprintf>("string->unsigned char", static_cast<unsigned char>('c'), "%hhu");
335
336 perf_test<std::string, structure_sprintf>("int->string", 100, "%d");
337 perf_test<std::string, structure_sprintf>("short->string", static_cast<short>(100), "%hd");
338 perf_test<std::string, structure_sprintf>("long int->string", 100l, "%ld");
339 perf_test<std::string, structure_sprintf>("long long->string", 100ll, "%lld");
340
341 perf_test<std::string, structure_sprintf>("unsigned int->string", static_cast<unsigned short>(100u), "%u");
342 perf_test<std::string, structure_sprintf>("unsigned short->string", 100u, "%hu");
343 perf_test<std::string, structure_sprintf>("unsigned long int->string", 100ul, "%lu");
344 perf_test<std::string, structure_sprintf>("unsigned long long->string", static_cast<boost::ulong_long_type>(100), "%llu");
345
346 // perf_test<bool, structure_sscanf>("bool->string", std::string("1"), "%");
347
348 perf_test<std::string, structure_sprintf>("float->string", 1.123f, "%f");
349 perf_test<std::string, structure_sprintf>("double->string", 1.123, "%lf");
350 perf_test<std::string, structure_sprintf>("long double->string", 1.123L, "%Lf");
351
352
353 string_like_test_set<to_char_conv>("char*");
354 string_like_test_set<to_uchar_conv>("unsigned char*");
355 string_like_test_set<to_schar_conv>("signed char*");
356 string_like_test_set<to_iterator_range>("iterator_range<char*>");
357 string_like_test_set<to_array_50>("array<char, 50>");
358
359 perf_test<int, structure_fake>("int->int", 100, "");
360 perf_test<double, structure_fake>("float->double", 100.0f, "");
361 perf_test<signed char, structure_fake>("char->signed char", 'c', "");
362
363
364 fout << "]\n"
365 << "[endsect]\n\n";
366 return 0;
367 }
368
369