Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include <kdbthread.hpp>
10 : #include <kdbtimer.hpp>
11 :
12 : // long long iterations = 100000000000LL; // elitebenchmark lookup
13 : // long long iterations = 100000LL; // elitebenchmark with/activate
14 : long long iterations = 1000LL; // elitebenchmark sync/reload benchmark
15 : // long long iterations = 100LL; // valgrind
16 :
17 : const int benchmarkIterations = 11; // is a good number to not need mean values for median
18 :
19 0 : const std::string filename = "check.txt";
20 0 : std::ofstream dump (filename);
21 :
22 : const uint32_t value = 55;
23 : const char * s_value = "55";
24 : const uint32_t othervalue = 66;
25 : const char * s_othervalue = "66";
26 :
27 0 : kdb::ThreadInteger::type add_contextual (kdb::ThreadInteger const & i1, kdb::ThreadInteger const & i2)
28 : {
29 0 : return i1 + i2;
30 : }
31 :
32 0 : std::unique_ptr<Timer> tSync[10]{
33 0 : std::unique_ptr<Timer> (new Timer ("layer sync0", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("layer sync1", Timer::quiet)),
34 0 : std::unique_ptr<Timer> (new Timer ("layer sync2", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("layer sync3", Timer::quiet)),
35 0 : std::unique_ptr<Timer> (new Timer ("layer sync4", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("layer sync5", Timer::quiet)),
36 0 : std::unique_ptr<Timer> (new Timer ("layer sync6", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("layer sync7", Timer::quiet)),
37 0 : std::unique_ptr<Timer> (new Timer ("layer sync8", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("layer sync9", Timer::quiet))
38 0 : };
39 :
40 0 : std::vector<std::shared_ptr<kdb::ThreadInteger>> createCV (kdb::KeySet & ks, kdb::ThreadContext & tc, int N)
41 : {
42 0 : std::vector<std::shared_ptr<kdb::ThreadInteger>> vi;
43 0 : for (long long i = 0; i < N; ++i)
44 : {
45 0 : std::ostringstream os;
46 0 : os << "/test/layer1";
47 : /*
48 : for (long long j = 0; j < i; ++j)
49 : {
50 : os << "/%layer" << j << "%";
51 : }
52 : */
53 0 : os << "/" << i;
54 : // std::cout << os.str().c_str() << std::endl;
55 0 : vi.push_back (std::make_shared<kdb::ThreadInteger> (
56 0 : ks, tc, kdb::Key (os.str ().c_str (), KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END)));
57 : }
58 0 : return vi;
59 : }
60 :
61 :
62 0 : __attribute__ ((noinline)) void benchmark_layer_syncN (long long N)
63 : {
64 0 : kdb::Coordinator c;
65 0 : kdb::ThreadContext tc (c);
66 0 : kdb::KeySet ks;
67 0 : kdb::ThreadInteger ti (ks, tc, kdb::Key ("/test/nolayer", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
68 0 : ti = 5;
69 0 : kdb::ThreadInteger::type x = ti;
70 :
71 0 : Timer & t = *tSync[N];
72 0 : t.start ();
73 0 : for (long long i = 0; i < iterations; ++i)
74 : {
75 0 : tc.sync ();
76 0 : x ^= add_contextual (ti, ti);
77 : }
78 0 : t.stop ();
79 0 : std::cout << t;
80 0 : dump << t.name << x << std::endl;
81 0 : }
82 :
83 0 : std::unique_ptr<Timer> tReload[10]{ std::unique_ptr<Timer> (new Timer ("layer reload0", Timer::quiet)),
84 0 : std::unique_ptr<Timer> (new Timer ("layer reload1", Timer::quiet)),
85 0 : std::unique_ptr<Timer> (new Timer ("layer reload2", Timer::quiet)),
86 0 : std::unique_ptr<Timer> (new Timer ("layer reload3", Timer::quiet)),
87 0 : std::unique_ptr<Timer> (new Timer ("layer reload4", Timer::quiet)),
88 0 : std::unique_ptr<Timer> (new Timer ("layer reload5", Timer::quiet)),
89 0 : std::unique_ptr<Timer> (new Timer ("layer reload6", Timer::quiet)),
90 0 : std::unique_ptr<Timer> (new Timer ("layer reload7", Timer::quiet)),
91 0 : std::unique_ptr<Timer> (new Timer ("layer reload8", Timer::quiet)),
92 0 : std::unique_ptr<Timer> (new Timer ("layer reload9", Timer::quiet)) };
93 :
94 0 : __attribute__ ((noinline)) void benchmark_kdb_reloadN (long long N)
95 : {
96 0 : kdb::Coordinator c;
97 0 : kdb::ThreadContext tc (c);
98 0 : kdb::KeySet ks;
99 0 : kdb::KDB kdb;
100 0 : kdb::KDB kdb2;
101 :
102 0 : kdb.get (ks, "/test");
103 0 : kdb2.get (ks, "/test");
104 0 : ks.append (kdb::Key ("system/test/key", KEY_VALUE, "value", KEY_END));
105 0 : kdb.set (ks, "/test");
106 0 : ks.append (kdb::Key ("system/test/key2", KEY_VALUE, "value2", KEY_END));
107 : // kdb2.set (ks, "/test");
108 :
109 0 : kdb::ThreadInteger ti (ks, tc, kdb::Key ("/test/nolayer", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
110 0 : ti = 5;
111 0 : kdb::ThreadInteger::type x = ti;
112 :
113 0 : Timer & t = *tReload[N];
114 :
115 0 : std::vector<kdb::KDB> kdbx;
116 0 : kdbx.resize (iterations); // really expensive operation, but need to be clean for every benchmark
117 :
118 0 : t.start ();
119 0 : for (long long i = 0; i < iterations; ++i)
120 : {
121 : // kdb.set(ks, "/test");
122 0 : kdbx[i].get (ks, "/test");
123 0 : tc.sync ();
124 0 : x ^= add_contextual (ti, ti);
125 : }
126 0 : t.stop ();
127 0 : std::cout << t;
128 0 : dump << t.name << x << std::endl;
129 0 : }
130 :
131 :
132 : template <int N>
133 0 : class Layer : public kdb::Layer
134 : {
135 : public:
136 0 : std::string id () const override
137 : {
138 0 : std::string ret ("layerX");
139 0 : ret[5] = ('0' + N);
140 0 : return ret;
141 : }
142 0 : std::string operator() () const override
143 : {
144 0 : std::string ret ("X");
145 0 : ret[0] = '0' + N;
146 0 : return ret;
147 : }
148 : };
149 :
150 :
151 0 : std::unique_ptr<Timer> tSwitch[10]{ std::unique_ptr<Timer> (new Timer ("layer switch0", Timer::quiet)),
152 0 : std::unique_ptr<Timer> (new Timer ("layer switch1", Timer::quiet)),
153 0 : std::unique_ptr<Timer> (new Timer ("layer switch2", Timer::quiet)),
154 0 : std::unique_ptr<Timer> (new Timer ("layer switch3", Timer::quiet)),
155 0 : std::unique_ptr<Timer> (new Timer ("layer switch4", Timer::quiet)),
156 0 : std::unique_ptr<Timer> (new Timer ("layer switch5", Timer::quiet)),
157 0 : std::unique_ptr<Timer> (new Timer ("layer switch6", Timer::quiet)),
158 0 : std::unique_ptr<Timer> (new Timer ("layer switch7", Timer::quiet)),
159 0 : std::unique_ptr<Timer> (new Timer ("layer switch8", Timer::quiet)),
160 0 : std::unique_ptr<Timer> (new Timer ("layer switch9", Timer::quiet)) };
161 :
162 0 : __attribute__ ((noinline)) void benchmark_layer_switchN (long long N)
163 : {
164 0 : kdb::Coordinator c;
165 0 : kdb::ThreadContext tc (c);
166 0 : kdb::KeySet ks;
167 0 : kdb::ThreadInteger ti (ks, tc, kdb::Key ("/test/nolayer", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
168 0 : ti = 5;
169 0 : kdb::ThreadInteger::type x = ti;
170 :
171 0 : Timer & t = *tSwitch[N];
172 0 : t.start ();
173 0 : for (long long i = 0; i < iterations; ++i)
174 : {
175 0 : if (N > 0) tc.activate<Layer<0>> ();
176 0 : if (N > 1) tc.activate<Layer<1>> ();
177 0 : if (N > 2) tc.activate<Layer<2>> ();
178 0 : if (N > 3) tc.activate<Layer<3>> ();
179 0 : if (N > 4) tc.activate<Layer<4>> ();
180 0 : if (N > 5) tc.activate<Layer<5>> ();
181 0 : if (N > 6) tc.activate<Layer<6>> ();
182 0 : if (N > 7) tc.activate<Layer<7>> ();
183 0 : if (N > 8) tc.activate<Layer<8>> ();
184 0 : if (N > 9) tc.activate<Layer<9>> ();
185 0 : x ^= add_contextual (ti, ti);
186 : }
187 0 : t.stop ();
188 0 : std::cout << t;
189 0 : dump << t.name << x << std::endl;
190 0 : }
191 :
192 0 : std::unique_ptr<Timer> tCV[10]{
193 0 : std::unique_ptr<Timer> (new Timer ("CV switch0", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("CV switch1", Timer::quiet)),
194 0 : std::unique_ptr<Timer> (new Timer ("CV switch2", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("CV switch3", Timer::quiet)),
195 0 : std::unique_ptr<Timer> (new Timer ("CV switch4", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("CV switch5", Timer::quiet)),
196 0 : std::unique_ptr<Timer> (new Timer ("CV switch6", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("CV switch7", Timer::quiet)),
197 0 : std::unique_ptr<Timer> (new Timer ("CV switch8", Timer::quiet)), std::unique_ptr<Timer> (new Timer ("CV switch9", Timer::quiet))
198 0 : };
199 :
200 0 : __attribute__ ((noinline)) void benchmark_cv_switchN (long long N)
201 : {
202 0 : kdb::Coordinator c;
203 0 : kdb::ThreadContext tc (c);
204 0 : kdb::KeySet ks;
205 0 : kdb::ThreadInteger ti (ks, tc, kdb::Key ("/test/nolayer", KEY_CASCADING_NAME, KEY_META, "default", s_value, KEY_END));
206 0 : ti = 5;
207 0 : kdb::ThreadInteger::type x = ti;
208 :
209 0 : std::vector<std::shared_ptr<kdb::ThreadInteger>> vi = createCV (ks, tc, N);
210 :
211 0 : Timer & t = *tCV[N];
212 0 : t.start ();
213 0 : for (long long i = 0; i < iterations; ++i)
214 : {
215 0 : if (N > 0) tc.activate (*vi[0]);
216 0 : if (N > 1) tc.activate (*vi[1]);
217 0 : if (N > 2) tc.activate (*vi[2]);
218 0 : if (N > 3) tc.activate (*vi[3]);
219 0 : if (N > 4) tc.activate (*vi[4]);
220 0 : if (N > 5) tc.activate (*vi[5]);
221 0 : if (N > 6) tc.activate (*vi[6]);
222 0 : if (N > 7) tc.activate (*vi[7]);
223 0 : if (N > 8) tc.activate (*vi[8]);
224 0 : if (N > 9) tc.activate (*vi[9]);
225 0 : x ^= add_contextual (ti, ti);
226 : }
227 0 : t.stop ();
228 0 : std::cout << t;
229 0 : dump << t.name << x << std::endl;
230 0 : }
231 :
232 : #include <unistd.h>
233 : #ifdef _WIN32
234 : #include <winsock2.h>
235 : #endif
236 :
237 0 : void computer_info ()
238 : {
239 : char hostname[1024];
240 0 : gethostname (hostname, 1023);
241 0 : std::cout << std::endl;
242 0 : std::cout << std::endl;
243 0 : std::cout << "hostname " << hostname << std::endl;
244 : #ifdef __GNUC__
245 0 : std::cout << "gcc: " << __GNUC__ << std::endl;
246 : #endif
247 : #ifdef __INTEL_COMPILER
248 : std::cout << "icc: " << __INTEL_COMPILER << std::endl;
249 : #endif
250 : #ifdef __clang__
251 : std::cout << "clang: " << __clang__ << std::endl;
252 : #endif
253 0 : std::cout << "sizeof(int) " << sizeof (int) << std::endl;
254 0 : std::cout << "sizeof(long) " << sizeof (long) << std::endl;
255 0 : std::cout << "sizeof(long long) " << sizeof (long long) << std::endl;
256 0 : std::cout << "sizeof(Integer::type) " << sizeof (kdb::ThreadInteger::type) << std::endl;
257 0 : std::cout << "value " << value << std::endl;
258 0 : std::cout << "othervalue " << othervalue << std::endl;
259 0 : std::cout << "iterations " << iterations << std::endl;
260 0 : std::cout << "filename " << filename << std::endl;
261 0 : std::cout << std::endl;
262 0 : }
263 :
264 0 : int main (int argc, char ** argv)
265 : {
266 0 : computer_info ();
267 0 : std::cout << std::endl;
268 :
269 : {
270 : using namespace kdb;
271 0 : std::string testRoot = "/test/";
272 0 : Key parent (testRoot, KEY_END);
273 :
274 0 : KDB first;
275 0 : KeySet firstReturned;
276 0 : first.get (firstReturned, parent);
277 0 : firstReturned.append (Key ("system" + testRoot + "key1", KEY_VALUE, "value1", KEY_END));
278 :
279 0 : KDB second;
280 0 : KeySet secondReturned;
281 0 : second.get (secondReturned, parent);
282 0 : secondReturned.append (Key ("system" + testRoot + "key2", KEY_VALUE, "value2", KEY_END));
283 :
284 0 : second.set (secondReturned, parent);
285 : // first.set(firstReturned, parent); // exception expected
286 : }
287 :
288 0 : if (argc == 2)
289 : {
290 0 : iterations = atoll (argv[1]);
291 : }
292 :
293 0 : for (int i = 0; i < benchmarkIterations; ++i)
294 : {
295 0 : std::cout << i << std::endl;
296 0 : for (int j = 0; j < 10; ++j)
297 : {
298 0 : benchmark_layer_syncN (j);
299 0 : benchmark_kdb_reloadN (j);
300 0 : benchmark_layer_switchN (j);
301 0 : benchmark_cv_switchN (j);
302 : }
303 : }
304 :
305 0 : for (int i = 0; i < 10; ++i)
306 : {
307 0 : std::cerr << i << "," << tSync[i]->getMedian () << "," << tReload[i]->getMedian () << "," << tSwitch[i]->getMedian () << ","
308 0 : << tCV[i]->getMedian () << std::endl;
309 : }
310 :
311 : // data << "value,benchmark" << std::endl;
312 0 : }
|