/* * Contribution from Aleksandar Lazic * * Build with : * gcc -O2 -o test_pools test_pools.c * or with dlmalloc too : * gcc -O2 -o test_pools -D USE_DLMALLOC test_pools.c -DUSE_DL_PREFIX dlmalloc.c */ #include #include #include #include #include #include static struct timeval timeval_current(void) { struct timeval tv; gettimeofday(&tv, NULL); return tv; } static double timeval_elapsed(struct timeval *tv) { struct timeval tv2 = timeval_current(); return (tv2.tv_sec - tv->tv_sec) + (tv2.tv_usec - tv->tv_usec)*1.0e-6; } #define torture_assert(test, expr, str) if (!(expr)) { \ printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \ test, __location__, #expr, str); \ return false; \ } #define torture_assert_str_equal(test, arg1, arg2, desc) \ if (strcmp(arg1, arg2)) { \ printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \ test, __location__, arg1, arg2, desc); \ return false; \ } /* added pools from haproxy */ #include /* * Returns a pointer to an area of <__len> bytes taken from the pool or * dynamically allocated. In the first case, <__pool> is updated to point to * the next element in the list. */ #define pool_alloc_from(__pool, __len) \ ({ \ void *__p; \ if ((__p = (__pool)) == NULL) \ __p = malloc(((__len) >= sizeof (void *)) ? \ (__len) : sizeof(void *)); \ else { \ __pool = *(void **)(__pool); \ } \ __p; \ }) /* * Puts a memory area back to the corresponding pool. * Items are chained directly through a pointer that * is written in the beginning of the memory area, so * there's no need for any carrier cell. This implies * that each memory area is at least as big as one * pointer. */ #define pool_free_to(__pool, __ptr) \ ({ \ *(void **)(__ptr) = (void *)(__pool); \ __pool = (void *)(__ptr); \ }) /* * Returns a pointer to type taken from the * pool or dynamically allocated. In the * first case, is updated to point to the * next element in the list. */ #define pool_alloc(type) \ ({ \ void *__p; \ if ((__p = pool_##type) == NULL) \ __p = malloc(sizeof_##type); \ else { \ pool_##type = *(void **)pool_##type; \ } \ __p; \ }) /* * Puts a memory area back to the corresponding pool. * Items are chained directly through a pointer that * is written in the beginning of the memory area, so * there's no need for any carrier cell. This implies * that each memory area is at least as big as one * pointer. */ #define pool_free(type, ptr) \ ({ \ *(void **)ptr = (void *)pool_##type; \ pool_##type = (void *)ptr; \ }) /* * This function destroys a pull by freeing it completely. * This should be called only under extreme circumstances. */ static inline void pool_destroy(void **pool) { void *temp, *next; next = pool; while (next) { temp = next; next = *(void **)temp; free(temp); } } #define sizeof_talloc 1000 /* measure the speed of hapx versus malloc */ static bool test_speed1(void) { void **pool_talloc = NULL; void *ctx = pool_alloc(talloc); unsigned count; const int loop = 1000; int i; struct timeval tv; printf("test: speed [\nhaproxy-pool VS MALLOC SPEED 2\n]\n"); tv = timeval_current(); count = 0; do { void *p1, *p2, *p3; for (i=0;i