Add benchmark support.
authorcedric <cedric>
Wed, 6 Aug 2008 15:54:56 +0000 (15:54 +0000)
committercedric <cedric@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Wed, 6 Aug 2008 15:54:56 +0000 (15:54 +0000)
git-svn-id: http://svn.enlightenment.org/svn/e/trunk/e17/proto/eina@35355 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

.cvsignore
configure.in
src/Makefile.am
src/tests/.cvsignore
src/tests/Makefile.am
src/tests/eina_bench.c [new file with mode: 0644]
src/tests/eina_bench.h [new file with mode: 0644]
src/tests/eina_bench_hash.c [new file with mode: 0644]

index bef6e97..dfcc543 100644 (file)
@@ -26,3 +26,4 @@ doc
 README
 mkinstalldirs
 coverage
+result
index f40ba68..f9870ae 100644 (file)
@@ -58,6 +58,23 @@ AC_ARG_ENABLE([coverage],
 AC_MSG_CHECKING([whether to use profiling instrumentation])
 AC_MSG_RESULT([$enable_coverage])
 
+# Benchmarking tests
+
+AC_ARG_ENABLE([tests],
+   [AC_HELP_STRING([--enable-tests], [enable tests @<:@default=no@:>@])],
+   [
+    if test "x${enableval}" = "xyes" ; then
+       enable_bench="yes"
+    else
+       enable_bench="no"
+    fi
+   ],
+   [enable_bench="no"]
+)
+AC_MSG_CHECKING([whether tests are built])
+AC_MSG_RESULT([${enable_bench}])
+AM_CONDITIONAL(EINA_ENABLE_BENCH, test "x${enable_bench}" = "xyes")
+
 # Ememoa memory pool
 
 AC_ARG_ENABLE([ememoa],
@@ -197,6 +214,7 @@ echo "Configuration Options Summary:"
 echo
 echo "  Tests................: ${enable_tests}"
 echo "  Coverage.............: ${enable_coverage}"
+echo "  Bench................: ${enable_bench}"
 echo
 echo "  Memory pool:"
 echo "    Ememoa.............: ${enable_ememoa}"
index 207ac0d..d7ebc22 100644 (file)
@@ -1,3 +1,15 @@
 SUBDIRS = lib include modules tests
 
 MAINTAINERCLEANFILES = Makefile.in
+
+if EINA_ENABLE_BENCH
+
+bench: all
+       make -C tests eina_bench
+
+else
+
+bench:
+       @echo "reconfigure with --enable-bench"
+
+endif
index 1d71993..6da7858 100644 (file)
@@ -6,3 +6,4 @@ Makefile
 .libs
 .deps
 eina_suite
+eina_bench
index ae86f33..aa04ec5 100644 (file)
@@ -1,11 +1,12 @@
 MAINTAINERCLEANFILES = Makefile.in
 
+benchdir = $(bindir)
+
 AM_CPPFLAGS = \
 -I$(top_srcdir)/src/lib \
 -I$(top_srcdir)/src/include \
 @CHECK_CFLAGS@
 
-
 if EINA_ENABLE_TESTS
 
 check_PROGRAMS = eina_suite
@@ -17,12 +18,26 @@ eina_test_array.c \
 eina_test_error.c \
 eina_test_magic.c \
 eina_test_inlist.c \
-eina_test_lalloc.c
+eina_test_main.c \
+eina_test_counter.c \
+eina_test_lalloc.c \
+eina_test_hash.c
 
 eina_suite_LDADD = @CHECK_LIBS@ $(top_builddir)/src/lib/libeina.la
 
-EXTRA_DIST = eina_suite.h
+endif
+
+if EINA_ENABLE_BENCH
+
+bench_PROGRAMS = eina_bench
+
+eina_bench_SOURCES = \
+eina_bench.c \
+eina_bench_hash.c
+
+eina_bench_LDADD = $(top_builddir)/src/lib/libeina.la
 
 endif
 
+EXTRA_DIST = eina_bench.h eina_suite.h
 
diff --git a/src/tests/eina_bench.c b/src/tests/eina_bench.c
new file mode 100644 (file)
index 0000000..b597acb
--- /dev/null
@@ -0,0 +1,185 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+
+#include "eina_bench.h"
+#include "eina_inlist.h"
+#include "eina_counter.h"
+
+typedef struct _Eina_Run Eina_Run;
+struct _Eina_Run
+{
+   Eina_Inlist __list;
+
+   Eina_Bench_Specimens cb;
+   const char *name;
+   int start;
+   int end;
+   int step;
+};
+
+struct _Eina_Bench
+{
+   const char *name;
+   const char *run;
+
+   Eina_Inlist *runs;
+};
+
+Eina_Bench *
+eina_bench_new(const char *name, const char *run)
+{
+   Eina_Bench *new;
+
+   new = calloc(1, sizeof (Eina_Bench));
+   if (!new) return NULL;
+
+   new->name = name;
+   new->run = run;
+
+   return new;
+}
+
+void
+eina_bench_delete(Eina_Bench *bench)
+{
+   if (!bench) return ;
+
+   while (bench->runs)
+     {
+       Eina_Run *run = (Eina_Run *) bench->runs;
+
+       bench->runs = eina_inlist_remove(bench->runs, bench->runs);
+       free(run);
+     }
+
+   free(bench);
+}
+
+void
+eina_bench_register(Eina_Bench *bench, const char *name, Eina_Bench_Specimens bench_cb,
+                   int count_start, int count_end, int count_step)
+{
+   Eina_Run *run;
+
+   if (!bench) return ;
+
+   run = calloc(1, sizeof (Eina_Run));
+   if (!run) return ;
+
+   run->cb = bench_cb;
+   run->name = name;
+   run->start = count_start;
+   run->end = count_end;
+   run->step = count_step;
+
+   bench->runs = eina_inlist_append(bench->runs, run);
+}
+
+void
+eina_bench_run(Eina_Bench *bench)
+{
+   FILE *main_script;
+   FILE *current_data;
+   Eina_Run *run;
+   char buffer[PATH_MAX];
+   Eina_Bool first = EINA_FALSE;
+
+   if (!bench) return ;
+
+   snprintf(buffer, PATH_MAX, "bench_%s_%s.gnuplot", bench->name, bench->run);
+
+   main_script = fopen(buffer, "w");
+   if (!main_script) return ;
+
+   fprintf(main_script,
+          "set   autoscale                        # scale axes automatically\n"
+          "unset log                              # remove any log-scaling\n"
+          "unset label                            # remove any previous labels\n"
+          "set xtic auto                          # set xtics automatically\n"
+          "set ytic auto                          # set ytics automatically\n"
+          "set logscale y\n"
+          "set terminal png size 1024,768\n"
+          "set output \"output_%s_%s.png\"\n"
+          "set title \"%s %s\n"
+          "set xlabel \"tests\"\n"
+          "set ylabel \"time\"\n"
+          "plot ", bench->name, bench->run, bench->name, bench->run);
+
+   eina_counter_init();
+
+   EINA_INLIST_ITER_NEXT(bench->runs, run)
+     {
+       Eina_Counter *counter;
+       int i;
+
+       snprintf(buffer, PATH_MAX, "bench_%s_%s.%s.data", bench->name, bench->run, run->name);
+
+       current_data = fopen(buffer, "w");
+       if (!current_data) continue ;
+
+       counter = eina_counter_add(run->name);
+
+       for (i = run->start; i < run->end; i += run->step)
+         {
+            fprintf(stderr, "Run %s: %i\n", run->name, i);
+            eina_counter_start(counter);
+
+            run->cb(i);
+
+            eina_counter_stop(counter, i);
+         }
+
+       eina_counter_dump(counter, current_data);
+
+       eina_counter_delete(counter);
+
+       fclose(current_data);
+
+       if (first == EINA_FALSE) first = EINA_TRUE;
+       else fprintf(main_script, ", \\\n");
+
+       fprintf(main_script,
+               "\"%s\" using 1:2 title \'%s\' with points",
+               buffer, run->name);
+     }
+
+   fprintf(main_script, "\n");
+
+   eina_counter_shutdown();
+
+   fclose(main_script);
+}
+
+typedef struct _Eina_Bench_Case Eina_Bench_Case;
+struct _Eina_Bench_Case
+{
+   const char *bench_case;
+   void (*build)(Eina_Bench *bench);
+};
+
+static const Eina_Bench_Case etc[] = {
+  { "Hash", eina_bench_hash },
+  { NULL, NULL }
+};
+
+int
+main(int argc, char **argv)
+{
+   Eina_Bench *test;
+   int i;
+
+   if (argc != 2) return -1;
+
+   for (i = 0; etc[i].bench_case != NULL; ++i)
+     {
+       test = eina_bench_new(etc[i].bench_case, argv[1]);
+       if (!test) continue ;
+
+       etc[i].build(test);
+
+       eina_bench_run(test);
+
+       eina_bench_delete(test);
+     }
+}
diff --git a/src/tests/eina_bench.h b/src/tests/eina_bench.h
new file mode 100644 (file)
index 0000000..0bac209
--- /dev/null
@@ -0,0 +1,13 @@
+#ifndef EINA_BENCH_H_
+#define EINA_BENCH_H_
+
+typedef struct _Eina_Bench Eina_Bench;
+typedef void (*Eina_Bench_Specimens)(int request);
+#define EINA_BENCH(Function) ((Eina_Bench_Specimens)Function)
+
+void eina_bench_register(Eina_Bench *bench, const char *name, Eina_Bench_Specimens bench_cb,
+                        int count_start, int count_end, int count_set);
+
+void eina_bench_hash(Eina_Bench *bench);
+
+#endif
diff --git a/src/tests/eina_bench_hash.c b/src/tests/eina_bench_hash.c
new file mode 100644 (file)
index 0000000..2dce462
--- /dev/null
@@ -0,0 +1,188 @@
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <time.h>
+
+#include "eina_hash.h"
+#include "eina_array.h"
+#include "eina_bench.h"
+
+static void
+eina_bench_insert_superfast(int request)
+{
+   Eina_Hash *hash = NULL;
+   Eina_Array *array = NULL;
+   int *tmp_val;
+   unsigned int i;
+
+   array = eina_array_new(1000);
+
+   hash = eina_hash_string_superfast_new();
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char *tmp_key = malloc(10);
+
+       tmp_val = malloc(sizeof (int));
+
+       if (!tmp_key || !tmp_val) continue ;
+
+       snprintf(tmp_key, 10, "%i", i);
+       *tmp_val = i;
+
+       eina_hash_add(hash, tmp_key, tmp_val);
+
+       eina_array_append(array, tmp_val);
+
+       free(tmp_key);
+     }
+
+   eina_hash_free(hash);
+
+   EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
+     free(tmp_val);
+
+   eina_array_free(array);
+}
+
+static void
+eina_bench_insert_djb2(int request)
+{
+   Eina_Hash *hash = NULL;
+   Eina_Array *array = NULL;
+   int *tmp_val;
+   unsigned int i;
+
+   array = eina_array_new(1000);
+
+   hash = eina_hash_string_djb2_new();
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char *tmp_key = malloc(10);
+
+       tmp_val = malloc(sizeof (int));
+
+       if (!tmp_key || !tmp_val) continue ;
+
+       snprintf(tmp_key, 10, "%i", i);
+       *tmp_val = i;
+
+       eina_hash_add(hash, tmp_key, tmp_val);
+
+       eina_array_append(array, tmp_val);
+
+       free(tmp_key);
+     }
+
+   eina_hash_free(hash);
+
+   EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
+     free(tmp_val);
+
+   eina_array_free(array);
+}
+
+static void
+eina_bench_lookup_superfast(int request)
+{
+   Eina_Hash *hash = NULL;
+   Eina_Array *array = NULL;
+   int *tmp_val;
+   unsigned int i;
+
+   array = eina_array_new(1000);
+
+   hash = eina_hash_string_superfast_new();
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char tmp_key[10];
+
+       tmp_val = malloc(sizeof (int));
+
+       if (!tmp_val) continue ;
+
+       snprintf(tmp_key, 10, "%i", i);
+       *tmp_val = i;
+
+       eina_hash_add(hash, tmp_key, tmp_val);
+
+       eina_array_append(array, tmp_val);
+     }
+
+   srand(time(NULL));
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char tmp_key[10];
+
+       snprintf(tmp_key, 10, "%i", rand() % request);
+
+       tmp_val = eina_hash_find(hash, tmp_key);
+     }
+
+   eina_hash_free(hash);
+
+   EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
+     free(tmp_val);
+
+   eina_array_free(array);
+}
+
+static void
+eina_bench_lookup_djb2(int request)
+{
+   Eina_Hash *hash = NULL;
+   Eina_Array *array = NULL;
+   int *tmp_val;
+   unsigned int i;
+
+   array = eina_array_new(1000);
+
+   hash = eina_hash_string_djb2_new();
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char *tmp_key = malloc(10);
+
+       tmp_val = malloc(sizeof (int));
+
+       if (!tmp_key || !tmp_val) continue ;
+
+       snprintf(tmp_key, 10, "%i", i);
+       *tmp_val = i;
+
+       eina_hash_add(hash, tmp_key, tmp_val);
+
+       eina_array_append(array, tmp_val);
+
+       free(tmp_key);
+     }
+
+   srand(time(NULL));
+
+   for (i = 0; i < (unsigned int) request; ++i)
+     {
+       char tmp_key[10];
+
+       snprintf(tmp_key, 10, "%i", rand() % request);
+
+       tmp_val = eina_hash_find(hash, tmp_key);
+     }
+
+   eina_hash_free(hash);
+
+   EINA_ARRAY_ITER_NEXT(array, i, tmp_val)
+     free(tmp_val);
+
+   eina_array_free(array);
+}
+
+void eina_bench_hash(Eina_Bench *bench)
+{
+   eina_bench_register(bench, "superfast-insert", EINA_BENCH(eina_bench_insert_superfast), 1000, 180000, 2500);
+   eina_bench_register(bench, "djb2-insert", EINA_BENCH(eina_bench_insert_djb2), 1000, 180000, 2500);
+   eina_bench_register(bench, "superfast-lookup", EINA_BENCH(eina_bench_lookup_superfast), 1000, 180000, 2500);
+   eina_bench_register(bench, "djb2-lookup", EINA_BENCH(eina_bench_lookup_djb2), 1000, 180000, 2500);
+}