1 //  (C) Copyright Antony Polukhin 2012-2014.
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 variant performance rvalue copy/assign performance
10 //
11 
12 #define BOOST_ERROR_CODE_HEADER_ONLY
13 #define BOOST_CHRONO_HEADER_ONLY
14 #include <boost/chrono.hpp>
15 
16 #include <boost/variant.hpp>
17 #include <string>
18 #include <vector>
19 
20     struct scope {
21         typedef boost::chrono::steady_clock test_clock;
22         typedef boost::chrono::milliseconds duration_t;
23         test_clock::time_point start_;
24         const char* const message_;
25 
scopescope26         explicit scope(const char* const message)
27             : start_(test_clock::now())
28             , message_(message)
29         {}
30 
~scopescope31         ~scope() {
32             std::cout << message_ << "   " << boost::chrono::duration_cast<duration_t>(test_clock::now() - start_) << std::endl;
33         }
34     };
35 
36 
37 
do_test(bool do_count_cleanup_time=false)38 static void do_test(bool do_count_cleanup_time = false) {
39     BOOST_STATIC_CONSTANT(std::size_t, c_run_count = 5000000);
40     typedef std::vector<char> str_t;
41     typedef boost::variant<int, str_t, float> var_t;
42 
43     const char hello1_c[] = "hello long word";
44     const str_t hello1(hello1_c, hello1_c + sizeof(hello1_c));
45 
46     const char hello2_c[] = "Helllloooooooooooooooooooooooooooooooo!!!!!!!!!!!!!";
47     const str_t hello2(hello2_c, hello2_c + sizeof(hello2_c));
48 
49     if (do_count_cleanup_time) {
50         std::cout << "#############################################\n";
51         std::cout << "#############################################\n";
52         std::cout << "NOW TIMES WITH DATA DESTRUCTION\n";
53         std::cout << "#############################################\n";
54     }
55 
56     std::vector<var_t> data_from, data_to;
57     data_from.resize(c_run_count, hello1);
58     data_to.reserve(c_run_count);
59     {
60         scope sc("boost::variant(const variant&) copying speed");
61         for (std::size_t i = 0; i < c_run_count; ++i) {
62             data_to.push_back(data_from[i]);
63 
64         }
65 
66         if (do_count_cleanup_time) {
67             data_to.clear();
68             data_from.clear();
69         }
70     }
71 
72     data_from.resize(c_run_count, hello1);
73     data_to.clear();
74     data_to.reserve(c_run_count);
75     {
76         scope sc("boost::variant(variant&&) moving speed");
77         for (std::size_t i = 0; i < c_run_count; ++i) {
78             data_to.push_back(boost::move(data_from[i]));
79         }
80 
81         if (do_count_cleanup_time) {
82             data_to.clear();
83             data_from.clear();
84         }
85     }
86 
87     std::cout << "#############################################\n";
88 
89     data_from.clear();
90     data_from.resize(c_run_count, hello2);
91     data_to.clear();
92     data_to.resize(c_run_count, hello2);
93     {
94         scope sc("boost::variant=(const variant&) copying speed on same types");
95         for (std::size_t i = 0; i < c_run_count; ++i) {
96             data_to[i] = data_from[i];
97         }
98 
99         if (do_count_cleanup_time) {
100             data_to.clear();
101             data_from.clear();
102         }
103     }
104 
105     data_from.resize(c_run_count, hello2);
106     data_to.clear();
107     data_to.resize(c_run_count, hello2);
108     {
109         scope sc("boost::variant=(variant&&) moving speed on same types");
110         for (std::size_t i = 0; i < c_run_count; ++i) {
111             data_to[i] = boost::move(data_from[i]);
112         }
113 
114         if (do_count_cleanup_time) {
115             data_to.clear();
116             data_from.clear();
117         }
118     }
119 
120     std::cout << "#############################################\n";
121 
122     data_from.clear();
123     data_from.resize(c_run_count, hello2);
124 
125     data_to.clear();
126     data_to.resize(c_run_count, var_t(0));
127     {
128         scope sc("boost::variant=(const variant&) copying speed on different types");
129         for (std::size_t i = 0; i < c_run_count; ++i) {
130             data_to[i] = data_from[i];
131         }
132 
133         if (do_count_cleanup_time) {
134             data_to.clear();
135             data_from.clear();
136         }
137     }
138 
139     data_from.resize(c_run_count, hello2);
140     data_to.clear();
141     data_to.resize(c_run_count, var_t(0));
142     {
143         scope sc("boost::variant=(variant&&) moving speed on different types");
144         for (std::size_t i = 0; i < c_run_count; ++i) {
145             data_to[i] = boost::move(data_from[i]);
146         }
147 
148         if (do_count_cleanup_time) {
149             data_to.clear();
150             data_from.clear();
151         }
152     }
153 
154     std::cout << "#############################################\n";
155 
156     data_from.clear();
157     data_from.resize(c_run_count, var_t(0));
158 
159     data_to.clear();
160     data_to.resize(c_run_count, hello2);
161     {
162         scope sc("boost::variant=(const variant&) copying speed on different types II");
163         for (std::size_t i = 0; i < c_run_count; ++i) {
164             data_to[i] = data_from[i];
165         }
166 
167         if (do_count_cleanup_time) {
168             data_to.clear();
169             data_from.clear();
170         }
171     }
172 
173     data_from.resize(c_run_count, var_t(0));
174     data_to.clear();
175     data_to.resize(c_run_count, hello2);
176     {
177         scope sc("boost::variant=(variant&&) moving speed on different types II");
178         for (std::size_t i = 0; i < c_run_count; ++i) {
179             data_to[i] = boost::move(data_from[i]);
180         }
181 
182         if (do_count_cleanup_time) {
183             data_to.clear();
184             data_from.clear();
185         }
186     }
187 
188 
189     std::cout << "#############################################\n";
190 
191     std::vector<str_t> s1(c_run_count, hello2);
192     data_to.clear();
193     data_to.resize(c_run_count, var_t(0));
194 
195     {
196         scope sc("boost::variant=(const T&) copying speed");
197         for (std::size_t i = 0; i < c_run_count; ++i) {
198             data_to[i] = s1[i];
199         }
200 
201         if (do_count_cleanup_time) {
202             data_to.clear();
203             s1.clear();
204         }
205     }
206 
207     std::vector<str_t> s2(c_run_count, hello2);
208     data_to.clear();
209     data_to.resize(c_run_count, var_t(0));
210     {
211         scope sc("boost::variant=(T&&) moving speed");
212         for (std::size_t i = 0; i < c_run_count; ++i) {
213             data_to[i] = boost::move(s2[i]);
214         }
215 
216         if (do_count_cleanup_time) {
217             data_to.clear();
218             s2.clear();
219         }
220     }
221 }
222 
223 
main()224 int main () {
225 
226 #ifndef BOOST_NO_CXX11_RVALUE_REFERENCES
227     std::cout << "# Running tests in C++11 mode (with rvalues).\n";
228 #else
229     std::cout << "# Running tests in C++03 mode (without rvalues).\n";
230 #endif
231 
232     do_test(false);
233     do_test(true);
234 }
235 
236 
237