CUBRID Engine  latest
unittests_area.c
Go to the documentation of this file.
1 /*
2  * Copyright 2008 Search Solution Corporation
3  * Copyright 2016 CUBRID Corporation
4  *
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  *
17  */
18 
19 /*
20  * unittest_area.c : unit tests for area manager
21  */
22 
23 #include "dbtype_def.h"
24 #include "db_set.h"
25 #include "porting.h"
26 #include "lock_free.h"
27 #include "object_domain.h"
28 #include "set_object.h"
29 
30 #include <stdio.h>
31 #include <pthread.h>
32 #include <sys/time.h>
33 #include <assert.h>
34 
35 #define strlen(s1) ((int) strlen(s1))
36 
37 #undef SERVER_MODE
38 /* suppress SERVER_MODE while including client module headers */
39 #include "class_object.h"
40 #include "object_template.h"
41 #define SERVER_MODE
42 
43 /* areate_create info */
46 {
47  const char *name; /* area name */
48  int entry_size; /* element size */
49  int alloc_cnt; /* alloc count */
50 };
51 
52 void *test_area_proc (void *param);
53 void *test_area_proc_1 (void *param);
54 void *test_area_proc_2 (void *param);
55 
56 /* print function */
57 static struct timeval start_time;
58 
59 static void
60 begin (char *test_name)
61 {
62 #define MSG_LEN 60
63  int i;
64 
65  printf ("Testing %s", test_name);
66  for (i = 0; i < MSG_LEN - strlen (test_name); i++)
67  {
68  putchar (' ');
69  }
70  printf ("...");
71 
72  gettimeofday (&start_time, NULL);
73 
74 #undef MSG_LEN
75 }
76 
77 static int
79 {
80  struct timeval end_time;
81  long long int elapsed_msec = 0;
82 
83  gettimeofday (&end_time, NULL);
84 
85  elapsed_msec = (end_time.tv_usec - start_time.tv_usec) / 1000;
86  elapsed_msec += (end_time.tv_sec - start_time.tv_sec) * 1000;
87 
88  printf (" %s [%9.3f sec]\n", "OK", (float) elapsed_msec / 1000.0f);
89  return NO_ERROR;
90 }
91 
92 
93 static int
94 fail (const char *message)
95 {
96  printf (" %s: %s\n", "FAILED", message);
97  assert (false);
98  return ER_FAILED;
99 }
100 
101 /* thread entry functions */
102 void *
103 test_area_proc (void *param)
104 {
105 #define NOPS 1000000 /* 1M */
106 
107  AREA *area_p = (AREA *) param;
108  void *entry = NULL;
109  int i, error;
110 
111  for (i = 0; i < NOPS; i++)
112  {
113  if (i % 2 == 0)
114  {
115  entry = area_alloc (area_p);
116  if (entry == NULL)
117  {
118  pthread_exit ((void *) ER_FAILED);
119  }
120  }
121  else
122  {
123  error = area_free (area_p, (void *) entry);
124  if (error != NO_ERROR)
125  {
126  pthread_exit ((void *) ER_FAILED);
127  }
128  }
129  }
130 
131  pthread_exit ((void *) NO_ERROR);
132 
133 #undef NOPS
134 }
135 
136 void *
137 test_area_proc_1 (void *param)
138 {
139 #define NOPS 1000000 /* 1M */
140 #define NCACHES 32
141 
142  AREA *area_p = (AREA *) param;
143  void *entry[NCACHES];
144  int idx, i, error;
145 
146 
147  for (idx = 0; idx < NCACHES; idx++)
148  {
149  entry[idx] = NULL;
150  }
151 
152  idx = 0;
153  for (i = 0; i < NOPS; i++)
154  {
155  if (entry[idx] != NULL)
156  {
157  error = area_free (area_p, (void *) entry[idx]);
158  if (error != NO_ERROR)
159  {
160  pthread_exit ((void *) ER_FAILED);
161  }
162  entry[idx] = NULL;
163  }
164 
165  entry[idx] = area_alloc (area_p);
166  if (entry[idx] == NULL)
167  {
168  pthread_exit ((void *) ER_FAILED);
169  }
170  idx++;
171  if (idx >= NCACHES)
172  {
173  idx = 0;
174  }
175  }
176 
177  for (i = 0; i < NCACHES; i++)
178  {
179  if (entry[idx] != NULL)
180  {
181  error = area_free (area_p, (void *) entry[idx]);
182  if (error != NO_ERROR)
183  {
184  pthread_exit ((void *) ER_FAILED);
185  }
186  entry[idx] = NULL;
187  }
188  idx++;
189  if (idx >= NCACHES)
190  {
191  idx = 0;
192  }
193  }
194 
195  pthread_exit ((void *) NO_ERROR);
196 
197 #undef NCACHES
198 #undef NOPS
199 }
200 
201 void *
202 test_area_proc_2 (void *param)
203 {
204 #define NOPS 1000000 /* 1M */
205 #define NCACHES 500
206 
207  AREA *area_p = (AREA *) param;
208  void *entry[NCACHES];
209  int idx, i, error;
210 
211 
212  for (idx = 0; idx < NCACHES; idx++)
213  {
214  entry[idx] = NULL;
215  }
216 
217  for (i = 0; i < NOPS; i++)
218  {
219  idx = rand () % NCACHES;
220  if (entry[idx] != NULL)
221  {
222  error = area_free (area_p, (void *) entry[idx]);
223  if (error != NO_ERROR)
224  {
225  pthread_exit ((void *) ER_FAILED);
226  }
227  entry[idx] = NULL;
228  }
229 
230  entry[idx] = area_alloc (area_p);
231  if (entry[idx] == NULL)
232  {
233  pthread_exit ((void *) ER_FAILED);
234  }
235  }
236 
237  for (idx = 0; idx < NCACHES; idx++)
238  {
239  if (entry[idx] != NULL)
240  {
241  error = area_free (area_p, (void *) entry[idx]);
242  if (error != NO_ERROR)
243  {
244  pthread_exit ((void *) ER_FAILED);
245  }
246  entry[idx] = NULL;
247  }
248  }
249 
250  pthread_exit ((void *) NO_ERROR);
251 
252 #undef NCACHES
253 #undef NOPS
254 }
255 
256 
257 /* test functions */
258 static int
259 test_area (AREA_CREATE_INFO * info, int nthreads, void *(*proc) (void *))
260 {
261 #define MAX_THREADS 64
262  AREA *area = NULL;
263  pthread_t threads[MAX_THREADS];
264  char msg[256];
265  int i;
266 
267  assert (info != NULL);
268  sprintf (msg, "%s(size:%d, count:%d), %d threads", info->name, info->entry_size, info->alloc_cnt, nthreads);
269  begin (msg);
270 
271  /* initialization */
272  if (nthreads > MAX_THREADS)
273  {
274  return fail ("too many threads");
275  }
276 
277  /* initialization */
278  area_init ();
279 
280  area = area_create (info->name, info->entry_size, info->alloc_cnt);
281  if (area == NULL)
282  {
283  return fail ("area create fail");
284  }
285 
286  /* multithreaded test */
287  for (i = 0; i < nthreads; i++)
288  {
289  if (pthread_create (&threads[i], NULL, proc, (void *) area) != NO_ERROR)
290  {
291  return fail ("thread create");
292  }
293  }
294 
295  for (i = 0; i < nthreads; i++)
296  {
297  void *retval;
298 
299  pthread_join (threads[i], &retval);
300  if (retval != NO_ERROR)
301  {
302  return fail ("thread proc error");
303  }
304  }
305 
306  /* results */
307  {
308  AREA_BLOCKSET_LIST *blockset;
309  AREA_BLOCK *block;
310  int i, j, blockset_cnt = 0, block_cnt = 0, chunk_count;
311  for (blockset = area->blockset_list; blockset != NULL; blockset = blockset->next)
312  {
313  for (i = 0; i < blockset->used_count; i++)
314  {
315  block = blockset->items[i];
316  assert (block != NULL);
317 
318  chunk_count = CEIL_PTVDIV (block->bitmap.entry_count, LF_BITFIELD_WORD_SIZE);
319 
320  for (j = 0; j < chunk_count; j++)
321  {
322  if (block->bitmap.bitfield[j])
323  {
324  return fail ("check bitmap status");
325  }
326  }
327 
328  block_cnt++;
329  }
330  blockset_cnt++;
331  }
332  printf (" Used %3d blocks(%2d blocksets). ", block_cnt, blockset_cnt);
333  }
334 
335  /* destory */
336  area_destroy (area);
337  area_final ();
338 
339  return success ();
340 
341 #undef MAX_THREADS
342 }
343 
344 /* program entry */
345 int
346 main (int argc, char **argv)
347 {
348  int i, j;
349 
350  /* test_cubrid_area */
351  {
352  AREA_CREATE_INFO cubrid_infos[] = {
353  {"Schema templates", sizeof (SM_TEMPLATE), 4}
354  ,
355  {"Domains", sizeof (TP_DOMAIN), 1024}
356  ,
357  {"Value containers", sizeof (DB_VALUE), 1024}
358  ,
359  {"Object templates", sizeof (OBJ_TEMPLATE), 32}
360  ,
361  {"Assignment templates", sizeof (OBJ_TEMPASSIGN), 64}
362  ,
363  {"Set references", sizeof (DB_COLLECTION), 1024}
364  ,
365  {"Set objects", sizeof (COL), 1024}
366  ,
367  {"Object list links", sizeof (DB_OBJLIST), 4096}
368  };
369 
370  printf ("============================================================\n");
371  printf ("Test simple get/free entry:\n");
372  for (j = 0; j < (int) DIM (cubrid_infos); j++)
373  {
374  for (i = 1; i <= 64; i *= 2)
375  {
376  if (test_area (&cubrid_infos[j], i, test_area_proc) != NO_ERROR)
377  {
378  goto fail;
379  }
380  }
381  }
382 
383  printf ("============================================================\n");
384  printf ("Test get/free entry with cache(32):\n");
385  for (j = 0; j < (int) DIM (cubrid_infos); j++)
386  {
387  for (i = 1; i <= 64; i *= 2)
388  {
389  if (test_area (&cubrid_infos[j], i, test_area_proc_1) != NO_ERROR)
390  {
391  goto fail;
392  }
393  }
394  }
395 
396  printf ("============================================================\n");
397  printf ("Test get/free entry with cache(500), random access:\n");
398  for (j = 0; j < (int) DIM (cubrid_infos); j++)
399  {
400  for (i = 1; i <= 64; i *= 2)
401  {
402  if (test_area (&cubrid_infos[j], i, test_area_proc_2) != NO_ERROR)
403  {
404  goto fail;
405  }
406  }
407  }
408  }
409 
410  /* test different alloc count */
411  {
412  AREA_CREATE_INFO diff_count_infos[] = {
413  {"size 1", 50, 32}
414  ,
415  {"size 2", 50, 32 * 2}
416  ,
417  {"size 4", 50, 32 * 4}
418  ,
419  {"size 8", 50, 32 * 8}
420  ,
421  {"size 16", 50, 32 * 16}
422  ,
423  {"size 32", 50, 32 * 32}
424  ,
425  {"size 64", 50, 32 * 64}
426  ,
427  {"size 128", 50, 32 * 128}
428  };
429 
430  printf ("============================================================\n");
431  printf ("Test simple get/free entry with different alloc count:\n");
432  for (i = 16; i <= 64; i *= 2)
433  {
434  for (j = 0; j < (int) DIM (diff_count_infos); j++)
435  {
436  if (test_area (&diff_count_infos[j], i, test_area_proc) != NO_ERROR)
437  {
438  goto fail;
439  }
440  }
441  }
442  }
443 
444 
445  /* all ok */
446  return 0;
447 
448 fail:
449  printf ("Unit tests failed!\n");
450  return ER_FAILED;
451 }
struct obj_tempassign OBJ_TEMPASSIGN
LF_BITMAP bitmap
Definition: area_alloc.h:53
struct db_value DB_VALUE
Definition: dbtype_def.h:1079
struct sm_template SM_TEMPLATE
Definition: class_object.h:703
#define NO_ERROR
Definition: error_code.h:46
static int test_area(AREA_CREATE_INFO *info, int nthreads, void *(*proc)(void *))
void area_destroy(AREA *area)
Definition: area_alloc.c:247
static void begin(char *test_name)
int argc
Definition: dynamic_load.c:951
#define strlen(s1)
#define ER_FAILED
Definition: error_code.h:47
struct tp_domain TP_DOMAIN
static int fail(const char *message)
AREA_BLOCKSET_LIST * next
Definition: area_alloc.h:65
#define NOPS
AREA * area_create(const char *name, size_t element_size, size_t alloc_count)
Definition: area_alloc.c:146
void area_init(void)
Definition: area_alloc.c:100
void * test_area_proc_2(void *param)
AREA_BLOCKSET_LIST * blockset_list
Definition: area_alloc.h:83
#define assert(x)
int main(int argc, char **argv)
#define NULL
Definition: freelistheap.h:34
struct obj_template OBJ_TEMPLATE
static int success()
#define LF_BITFIELD_WORD_SIZE
static struct timeval start_time
#define NCACHES
#define CEIL_PTVDIV(dividend, divisor)
Definition: memory_alloc.h:50
struct db_set DB_COLLECTION
Definition: dbtype_def.h:840
static void error(const char *msg)
Definition: gencat.c:331
std::atomic< unsigned int > * bitfield
void * test_area_proc(void *param)
#define MAX_THREADS
const char ** argv
Definition: dynamic_load.c:952
SETOBJ COL
Definition: set_object.h:96
void * area_alloc(AREA *area)
Definition: area_alloc.c:360
#define MSG_LEN
int area_free(AREA *area, void *ptr)
Definition: area_alloc.c:514
AREA_BLOCK * items[AREA_BLOCKSET_SIZE]
Definition: area_alloc.h:66
int i
Definition: dynamic_load.c:954
void * test_area_proc_1(void *param)
void area_final(void)
Definition: area_alloc.c:119
struct db_objlist DB_OBJLIST
Definition: dbtype_def.h:437
const char * name