ARB
arb_perf_test.cxx
Go to the documentation of this file.
1 // =============================================================== //
2 // //
3 // File : arb_perf_test.cxx //
4 // Purpose : //
5 // //
6 // Institute of Microbiology (Technical University Munich) //
7 // http://www.arb-home.de/ //
8 // //
9 // =============================================================== //
10 
11 #include <arbdbt.h>
12 
13 #include <climits>
14 #include <ctime>
15 #include <sys/time.h>
16 
17 // --------------------------------------------------------------------------------
18 // data used for tests
19 
21 static GBDATA *gb_main = NULp;
22 
23 // --------------------------------------------------------------------------------
24 // Test functions
25 
26 static void iterate(GBDATA *gbd) {
27  for (GBDATA *gb_child = GB_child(gbd); gb_child; gb_child = GB_nextChild(gb_child)) {
28  iterate(gb_child);
29  }
30 }
31 
32 static void test_GB_iterate_DB() { // iterate through all DB elements
33  iterate(gb_main);
34 }
35 static void test_GB_find_string() {
36  GB_find_string(gb_species_data, "full_name", "asdfasdf", GB_IGNORE_CASE, SEARCH_GRANDCHILD);
37 }
39  // field 'name' is indexed by GBT_open!
40  GB_find_string(gb_species_data, "name", "asdfasdf", GB_IGNORE_CASE, SEARCH_GRANDCHILD);
41 }
42 
43 // --------------------------------------------------------------------------------
44 
45 static void noop() {
46 }
47 
48 typedef void (*test_fun)();
49 
50 struct Test {
51  const char *name;
53 };
54 
55 #define TEST(fun) { #fun, test_##fun }
56 
57 static Test Test[] = {
58  TEST(GB_iterate_DB),
60  TEST(GB_find_string_indexed),
61 
62  { NULp, NULp },
63 };
64 
65 // --------------------------------------------------------------------------------
66 
67 static long callDelay(long loops);
68 
69 #define SECOND 1000000
70 #define WANTED_TIME 5*SECOND // time reserved for each test
71 
72 static long run_test(test_fun fun, long loops, double *perCall) {
73  // returns time for test 'fun' in microseconds
74  struct timeval t1;
75  struct timeval t2;
76 
77  gettimeofday(&t1, NULp);
78  for (int i = 0; i<loops; ++i) {
79  fun();
80  }
81  gettimeofday(&t2, NULp);
82 
83  long usecs = t2.tv_sec - t1.tv_sec;
84  usecs *= SECOND;
85  usecs += t2.tv_usec - t1.tv_usec;
86 
87  static bool recurse = true;
88  if (recurse) {
89  recurse = false;
90  usecs -= callDelay(loops);
91  recurse = true;
92  }
93 
94  *perCall = double(usecs)/loops;
95 
96  return usecs;
97 }
98 
99 static long callDelay(long loops) {
100  static GB_HASH *call_delay_hash = NULp;
101  if (!call_delay_hash) call_delay_hash = GBS_create_hash(100, GB_MIND_CASE);
102 
103  const char *loopKey = GBS_global_string("%li", loops);
104  long delay = GBS_read_hash(call_delay_hash, loopKey);
105  if (!delay) {
106  double perCall;
107  delay = run_test(noop, loops, &perCall);
108  GBS_write_hash(call_delay_hash, loopKey, delay);
109  }
110  return delay;
111 }
112 
113 static long estimate_loops(test_fun fun) {
114  long loops = 1;
115  double perCall;
116  long duration = run_test(fun, loops, &perCall);
117 
118  while (duration<1000) {
119  loops = (loops*10000.0)/duration+1;
120  if (loops>0) {
121  duration = run_test(fun, loops, &perCall);
122  }
123  }
124 
125  loops = (loops*double(WANTED_TIME))/duration+1;
126  if (loops <= 0) loops = LONG_MAX;
127  return loops;
128 }
129 
130 static long count_elements(GBDATA *gbd) {
131  long count = 0;
132  for (GBDATA *gb_child = GB_child(gbd); gb_child; gb_child = GB_nextChild(gb_child)) {
133  count += count_elements(gb_child);
134  }
135  return count+1; // self
136 }
137 
138 int ARB_main(int argc, char *argv[]) {
139  GB_ERROR error = NULp;
140 
141  if (argc == 0) {
142  fprintf(stderr, "arb_perf_test source.arb\n");
143  fprintf(stderr, "Test performance of some commands - see source code\n");
144 
145  error = "Missing arguments";
146  }
147  else {
148  const char *in = argv[1];
149  gb_main = GBT_open(in, "rw");
150 
151  if (!gb_main) {
152  error = GB_await_error();
153  }
154  else {
155  // init test data
156  {
157  GB_transaction ta(gb_main);
158  gb_species_data = GBT_get_species_data(gb_main);
159  }
160 
161  printf("Loaded DB '%s'\n", in);
162  printf(" * contains %li elements\n", count_elements(gb_main));
163  printf(" * contains %li species\n", GBT_get_species_count(gb_main));
164 
165  printf("Running tests:\n");
166  for (int test = 0; Test[test].name; ++test) {
167  GB_transaction ta(gb_main);
168 
169  double perCall;
170  long esti_loops = estimate_loops(Test[test].fun);
171  long usecs = run_test(Test[test].fun, esti_loops, &perCall);
172 
173  printf("Test #%i: %-25s %10li loops = %10li us (%10.2f us/call, %10.2f calls/sec)\n",
174  test+1,
175  Test[test].name,
176  esti_loops,
177  usecs,
178  perCall,
179  SECOND/perCall);
180  }
181 
182  GB_close(gb_main);
183  }
184  }
185 
186  if (error) {
187  fprintf(stderr, "arb_perf_test: Error: %s\n", error);
188  return EXIT_FAILURE;
189  }
190 
191  return EXIT_SUCCESS;
192 }
const char * GB_ERROR
Definition: arb_core.h:25
GBDATA * GB_child(GBDATA *father)
Definition: adquery.cxx:322
long GBS_write_hash(GB_HASH *hs, const char *key, long val)
Definition: adhash.cxx:454
static void iterate(GBDATA *gbd)
static GBDATA * gb_main
test_fun fun
static void noop()
void(* test_fun)()
static GBDATA * gb_species_data
const char * GBS_global_string(const char *templat,...)
Definition: arb_msg.cxx:203
static void test_GB_find_string()
#define EXIT_SUCCESS
Definition: arb_a2ps.c:154
#define SECOND
GBDATA * GBT_open(const char *path, const char *opent)
Definition: adtools.cxx:524
const char * name
GB_ERROR GB_await_error()
Definition: arb_msg.cxx:342
static void test_GB_find_string_indexed()
static void error(const char *msg)
Definition: mkptypes.cxx:96
#define EXIT_FAILURE
Definition: arb_a2ps.c:157
#define TEST(fun)
static void test_GB_iterate_DB()
#define WANTED_TIME
GBDATA * GB_find_string(GBDATA *gbd, const char *key, const char *str, GB_CASE case_sens, GB_SEARCH_TYPE gbs)
Definition: adquery.cxx:302
#define NULp
Definition: cxxforward.h:116
static long count_elements(GBDATA *gbd)
static long callDelay(long loops)
GBDATA * GB_nextChild(GBDATA *child)
Definition: adquery.cxx:326
int ARB_main(int argc, char *argv[])
long GBT_get_species_count(GBDATA *gb_main)
Definition: aditem.cxx:207
GB_transaction ta(gb_var)
static long estimate_loops(test_fun fun)
static long run_test(test_fun fun, long loops, double *perCall)
long GBS_read_hash(const GB_HASH *hs, const char *key)
Definition: adhash.cxx:392
void GB_close(GBDATA *gbd)
Definition: arbdb.cxx:655
GB_HASH * GBS_create_hash(long estimated_elements, GB_CASE case_sens)
Definition: adhash.cxx:253
GBDATA * GBT_get_species_data(GBDATA *gb_main)
Definition: aditem.cxx:105