Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief benchmark for getenv
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : *
8 : */
9 :
10 : #include <kdbtimer.hpp>
11 : #include <keyset.hpp>
12 :
13 : #include <fstream>
14 : #include <iostream>
15 : #include <unistd.h>
16 :
17 : #include <dlfcn.h>
18 : #include <string.h>
19 : extern "C" char ** environ;
20 :
21 :
22 : const long long nr_keys = 30;
23 :
24 : // long long iterations = 100000000000LL; // elitebenchmark lookup
25 : long long iterations = 1000000LL; // elitebenchmark
26 : // long long iterations = 100LL; // valgrind
27 :
28 : // not needed in benchmarks:
29 0 : long long iterations1 = iterations / 100;
30 :
31 : const int benchmarkIterations = 11; // is a good number to not need mean values for median
32 :
33 0 : const std::string filename = "check.txt";
34 :
35 0 : const std::string csvfilename = "data.csv";
36 :
37 0 : std::ofstream dump (filename);
38 0 : std::ofstream data (csvfilename);
39 :
40 :
41 : // from libgetenv
42 : namespace ckdb
43 : {
44 : char * elektraBootstrapGetEnv (const char * name);
45 : }
46 :
47 :
48 : // very fast benchmarks without any if:
49 :
50 0 : __attribute__ ((noinline)) void benchmark_nothing ()
51 : {
52 0 : static Timer t ("nothing");
53 :
54 0 : t.start ();
55 0 : t.stop ();
56 0 : std::cout << t;
57 0 : dump << t.name << std::endl;
58 0 : }
59 :
60 0 : __attribute__ ((noinline)) void benchmark_getenv ()
61 : {
62 0 : static Timer t ("elektra getenv");
63 :
64 0 : t.start ();
65 0 : for (long long i = 0; i < iterations; ++i)
66 : {
67 0 : getenv ("HELLO");
68 0 : __asm__("");
69 : }
70 0 : t.stop ();
71 0 : std::cout << t;
72 0 : dump << t.name << std::endl;
73 0 : }
74 :
75 0 : __attribute__ ((noinline)) void benchmark_dl_next_getenv ()
76 : {
77 0 : static Timer t ("dl next getenv");
78 0 : typedef char * (*gfcn) (const char *);
79 0 : union Sym
80 : {
81 : void * d;
82 : gfcn f;
83 : } sym;
84 0 : sym.d = dlsym (RTLD_NEXT, "getenv");
85 0 : gfcn dl_libc_getenv = sym.f;
86 :
87 0 : t.start ();
88 0 : for (long long i = 0; i < iterations; ++i)
89 : {
90 0 : dl_libc_getenv ("HELLO");
91 0 : __asm__("");
92 : }
93 0 : t.stop ();
94 0 : std::cout << t;
95 0 : dump << t.name << std::endl;
96 0 : }
97 :
98 :
99 0 : __attribute__ ((noinline)) void benchmark_libc_getenv ()
100 : {
101 0 : typedef char * (*gfcn) (const char *);
102 0 : union Sym
103 : {
104 : void * d;
105 : gfcn f;
106 : } sym;
107 :
108 0 : void * handle = dlopen ("/lib/x86_64-linux-gnu/libc-2.19.so", RTLD_NOW);
109 0 : if (!handle)
110 : {
111 0 : handle = dlopen ("/lib/i386-linux-gnu/libc-2.19.so", RTLD_NOW);
112 : }
113 0 : if (!handle)
114 : {
115 0 : std::cout << "Aborting, could not find libc" << std::endl;
116 0 : return;
117 : }
118 :
119 0 : static Timer t ("libc getenv");
120 0 : sym.d = dlsym (handle, "getenv");
121 0 : gfcn dl_libc_getenv = sym.f;
122 :
123 0 : t.start ();
124 0 : for (long long i = 0; i < iterations; ++i)
125 : {
126 0 : dl_libc_getenv ("HELLO");
127 0 : __asm__("");
128 : }
129 0 : t.stop ();
130 0 : std::cout << t;
131 0 : dump << t.name << std::endl;
132 : }
133 :
134 :
135 0 : __attribute__ ((noinline)) void benchmark_bootstrap_getenv ()
136 : {
137 0 : static Timer t ("bootstrap getenv");
138 0 : t.start ();
139 0 : for (long long i = 0; i < iterations; ++i)
140 : {
141 0 : ckdb::elektraBootstrapGetEnv ("HELLO");
142 0 : __asm__("");
143 : }
144 0 : t.stop ();
145 0 : std::cout << t;
146 0 : dump << t.name << std::endl;
147 0 : }
148 :
149 0 : __attribute__ ((noinline)) void benchmark_kslookup ()
150 : {
151 0 : static Timer t ("kslookup");
152 0 : using namespace kdb; // needed for KS_END
153 0 : kdb::KeySet ks (100,
154 : /*
155 : *kdb::Key("user:/env/override/some", KEY_END),
156 : *kdb::Key("user:/env/override/a/key", KEY_END),
157 : *kdb::Key("user:/env/override/b/key", KEY_END),
158 : *kdb::Key("user:/env/override/c/key", KEY_END),
159 : *kdb::Key("user:/env/override/d/key", KEY_END),
160 : */
161 0 : KS_END);
162 0 : for (int i = 0; i < nr_keys; ++i)
163 : {
164 0 : char x[100];
165 0 : sprintf (x, "user:/env/override/hello%d_%d", i, i);
166 0 : ks.append (*kdb::Key (x, KEY_END));
167 : }
168 0 : Key lookupKey ("user:/env/override/HELLO", KEY_END);
169 0 : t.start ();
170 0 : for (long long i = 0; i < iterations; ++i)
171 : {
172 0 : ks.lookup (lookupKey);
173 0 : __asm__("");
174 : }
175 0 : t.stop ();
176 0 : std::cout << t;
177 0 : }
178 :
179 0 : void computer_info ()
180 : {
181 0 : std::cout << std::endl;
182 0 : std::cout << std::endl;
183 : #ifndef _WIN32
184 0 : char hostname[1024];
185 0 : gethostname (hostname, 1023);
186 0 : std::cout << "hostname " << hostname << std::endl;
187 : #endif
188 : #ifdef __GNUC__
189 0 : std::cout << "gcc: " << __GNUC__ << std::endl;
190 : #endif
191 : #ifdef __INTEL_COMPILER
192 : std::cout << "icc: " << __INTEL_COMPILER << std::endl;
193 : #endif
194 : #ifdef __clang__
195 : std::cout << "clang: " << __clang__ << std::endl;
196 : #endif
197 0 : std::cout << "sizeof(int) " << sizeof (int) << std::endl;
198 0 : std::cout << "sizeof(long) " << sizeof (long) << std::endl;
199 0 : std::cout << "sizeof(long long) " << sizeof (long long) << std::endl;
200 0 : std::cout << "iterations " << iterations << std::endl;
201 0 : std::cout << "filename " << filename << std::endl;
202 0 : std::cout << std::endl;
203 0 : }
204 :
205 0 : int main (int argc, char ** argv)
206 : {
207 0 : computer_info ();
208 :
209 0 : clearenv ();
210 0 : for (int i = 0; i < nr_keys; ++i)
211 : {
212 0 : char x[100];
213 0 : sprintf (x, "hello%d_%d", i, i);
214 0 : setenv (x, x, 0);
215 : }
216 :
217 0 : if (argc == 2)
218 : {
219 0 : iterations = atoll (argv[1]);
220 0 : iterations1 = iterations / 100;
221 : }
222 :
223 0 : for (int i = 0; i < benchmarkIterations; ++i)
224 : {
225 0 : std::cout << i << std::endl;
226 :
227 0 : benchmark_nothing ();
228 0 : benchmark_getenv ();
229 0 : benchmark_libc_getenv ();
230 0 : benchmark_bootstrap_getenv ();
231 :
232 0 : benchmark_kslookup ();
233 :
234 : // benchmark_hashmap();
235 : // benchmark_hashmap_find();
236 : }
237 :
238 0 : data << "value,benchmark" << std::endl;
239 0 : }
|