EFL 1.7 svn doobies
[profile/ivi/eina.git] / src / lib / eina_benchmark.c
1 /* EINA - EFL data type library
2  * Copyright (C) 2008 Cedric Bail
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library;
16  * if not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #endif
22
23 #ifdef HAVE_ALLOCA_H
24 # include <alloca.h>
25 #elif defined __GNUC__
26 # define alloca __builtin_alloca
27 #elif defined _AIX
28 # define alloca __alloca
29 #elif defined _MSC_VER
30 # include <malloc.h>
31 # define alloca _alloca
32 #else
33 # include <stddef.h>
34 # ifdef  __cplusplus
35 extern "C"
36 # endif
37 void *alloca (size_t);
38 #endif
39
40 #include <stdlib.h>
41 #include <stdio.h>
42 #include <string.h>
43
44 #ifdef HAVE_EVIL
45 # include <Evil.h>
46 #endif
47
48 #include "eina_config.h"
49 #include "eina_private.h"
50 #include "eina_log.h"
51 #include "eina_benchmark.h"
52 #include "eina_inlist.h"
53 #include "eina_list.h"
54 #include "eina_counter.h"
55
56 /*============================================================================*
57 *                                  Local                                     *
58 *============================================================================*/
59
60 /**
61  * @cond LOCAL
62  */
63
64 #define EINA_BENCHMARK_FILENAME_MASK "bench_%s_%s.gnuplot"
65 #define EINA_BENCHMARK_DATA_MASK "bench_%s_%s.%s.data"
66
67 typedef struct _Eina_Run Eina_Run;
68 struct _Eina_Run
69 {
70    EINA_INLIST;
71
72    Eina_Benchmark_Specimens cb;
73    const char *name;
74    int start;
75    int end;
76    int step;
77 };
78
79 struct _Eina_Benchmark
80 {
81    const char *name;
82    const char *run;
83
84    Eina_Inlist *runs;
85    Eina_List *names;
86 };
87
88 static int _eina_benchmark_log_dom = -1;
89
90 #ifdef ERR
91 #undef ERR
92 #endif
93 #define ERR(...) EINA_LOG_DOM_ERR(_eina_benchmark_log_dom, __VA_ARGS__)
94
95 #ifdef DBG
96 #undef DBG
97 #endif
98 #define DBG(...) EINA_LOG_DOM_DBG(_eina_benchmark_log_dom, __VA_ARGS__)
99
100 /**
101  * @endcond
102  */
103
104 /*============================================================================*
105 *                                 Global                                     *
106 *============================================================================*/
107
108 /**
109  * @internal
110  * @brief Initialize the benchmark module.
111  *
112  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
113  *
114  * This function sets up the benchmark module of Eina. It is called by
115  * eina_init().
116  *
117  * @see eina_init()
118  */
119 Eina_Bool
120 eina_benchmark_init(void)
121 {
122    _eina_benchmark_log_dom = eina_log_domain_register("eina_benchmark",
123                                                       EINA_LOG_COLOR_DEFAULT);
124    if (_eina_benchmark_log_dom < 0)
125      {
126         EINA_LOG_ERR("Could not register log domain: eina_benchmark");
127         return EINA_FALSE;
128      }
129
130    return EINA_TRUE;
131 }
132
133 /**
134  * @internal
135  * @brief Shut down the benchmark module.
136  *
137  * @return #EINA_TRUE on success, #EINA_FALSE on failure.
138  *
139  * This function shuts down the benchmark module set up by
140  * eina_benchmark_init(). It is called by eina_shutdown().
141  *
142  * @see eina_shutdown()
143  */
144 Eina_Bool
145 eina_benchmark_shutdown(void)
146 {
147    eina_log_domain_unregister(_eina_benchmark_log_dom);
148    _eina_benchmark_log_dom = -1;
149    return EINA_TRUE;
150 }
151
152 /*============================================================================*
153 *                                   API                                      *
154 *============================================================================*/
155
156 EAPI Eina_Benchmark *
157 eina_benchmark_new(const char *name, const char *run)
158 {
159    Eina_Benchmark *new;
160
161         eina_error_set(0);
162    new = calloc(1, sizeof (Eina_Benchmark));
163    if (!new)
164      {
165         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
166         return NULL;
167      }
168
169    new->name = name;
170    new->run = run;
171
172    return new;
173 }
174
175 EAPI void
176 eina_benchmark_free(Eina_Benchmark *bench)
177 {
178    Eina_Array *names;
179
180    if (!bench)
181       return;
182
183    while (bench->runs)
184      {
185         Eina_Run *run = (Eina_Run *)bench->runs;
186
187         bench->runs = eina_inlist_remove(bench->runs, bench->runs);
188         free(run);
189      }
190
191    EINA_LIST_FREE(bench->names, names)
192    {
193       Eina_Array_Iterator it;
194       char *tmp;
195       unsigned int i;
196
197       EINA_ARRAY_ITER_NEXT(names, i, tmp, it)
198         free(tmp);
199
200       eina_array_free(names);
201    }
202
203    free(bench);
204 }
205
206 EAPI Eina_Bool
207 eina_benchmark_register(Eina_Benchmark *bench,
208                         const char *name,
209                         Eina_Benchmark_Specimens bench_cb,
210                         int count_start,
211                         int count_end,
212                         int count_step)
213 {
214    Eina_Run *run;
215
216    if (!bench)
217       return EINA_FALSE;
218
219    if (count_step == 0)
220       return EINA_FALSE;
221
222         eina_error_set(0);
223    run = calloc(1, sizeof (Eina_Run));
224    if (!run)
225      {
226         eina_error_set(EINA_ERROR_OUT_OF_MEMORY);
227         return EINA_FALSE;
228      }
229
230    run->cb = bench_cb;
231    run->name = name;
232    run->start = count_start;
233    run->end = count_end;
234    run->step = count_step;
235
236    bench->runs = eina_inlist_append(bench->runs, EINA_INLIST_GET(run));
237
238    return EINA_TRUE;
239 }
240
241 EAPI Eina_Array *
242 eina_benchmark_run(Eina_Benchmark *bench)
243 {
244    FILE *main_script;
245    FILE *current_data;
246    Eina_Array *ea;
247    Eina_Run *run;
248    char *buffer;
249    Eina_Bool first = EINA_FALSE;
250    size_t length;
251
252    if (!bench)
253       return NULL;
254
255    length = strlen(EINA_BENCHMARK_FILENAME_MASK) + strlen(bench->name) + strlen(
256          bench->run);
257
258    buffer = alloca(sizeof (char) * length);
259    if (!buffer)
260       return NULL;
261
262    snprintf(buffer,
263             length,
264             EINA_BENCHMARK_FILENAME_MASK,
265             bench->name,
266             bench->run);
267
268    main_script = fopen(buffer, "w");
269    if (!main_script)
270       return NULL;
271
272    ea = eina_array_new(16);
273    if (!ea)
274      {
275         fclose(main_script);
276         return NULL;
277      }
278
279    eina_array_push(ea, strdup(buffer));
280
281    fprintf(
282       main_script,
283       "set   autoscale                        # scale axes automatically\n"
284       "unset log                              # remove any log-scaling\n"
285       "unset label                            # remove any previous labels\n"
286       "set xtic auto                          # set xtics automatically\n"
287       "set ytic auto                          # set ytics automatically\n"
288 /*     "set logscale y\n" */
289       "set terminal png size 1024,768\n"
290       "set output \"output_%s_%s.png\"\n"
291       "set title \"%s %s\n"
292       "set xlabel \"tests\"\n"
293       "set ylabel \"time\"\n"
294       "plot ",
295       bench->name,
296       bench->run,
297       bench->name,
298       bench->run);
299
300    EINA_INLIST_FOREACH(bench->runs, run)
301    {
302       Eina_Counter *counter;
303       char *result;
304       size_t tmp;
305       int i;
306
307       tmp = strlen(EINA_BENCHMARK_DATA_MASK) + strlen(bench->name) + strlen(
308             bench->run) + strlen(run->name);
309       if (tmp > length)
310         {
311            buffer = alloca(sizeof (char) * tmp);
312            length = tmp;
313         }
314
315       snprintf(buffer,
316                length,
317                EINA_BENCHMARK_DATA_MASK,
318                bench->name,
319                bench->run,
320                run->name);
321
322       current_data = fopen(buffer, "w");
323       if (!current_data)
324          continue;
325
326       eina_array_push(ea, strdup(buffer));
327
328       counter = eina_counter_new(run->name);
329
330       for (i = run->start; i < run->end; i += run->step)
331         {
332            fprintf(stderr, "Run %s: %i\n", run->name, i);
333            eina_counter_start(counter);
334
335            run->cb(i);
336
337            eina_counter_stop(counter, i);
338         }
339
340       result = eina_counter_dump(counter);
341       if (result)
342         {
343            fprintf(current_data, "%s", result);
344            free(result);
345         }
346
347       eina_counter_free(counter);
348
349       fclose(current_data);
350
351       if (first == EINA_FALSE)
352          first = EINA_TRUE;
353       else
354          fprintf(main_script, ", \\\n");
355
356          fprintf(main_script,
357               "\"%s\" using 1:2 title \'%s\' with line",
358               buffer, run->name);
359    }
360
361          fprintf(main_script, "\n");
362
363          fclose(main_script);
364
365    bench->names = eina_list_append(bench->names, ea);
366
367    return ea;
368 }
369
370 /**
371  * @}
372  */