blob: c8558dba9bc1be423f1cfb0c4acf4cb329520fee [file] [log] [blame]
Willy Tarreauad99d292007-05-12 15:51:02 +02001/*
2 * Contribution from Aleksandar Lazic <al-haproxy@none.at>
3 *
Willy Tarreau119680b2007-05-12 16:14:55 +02004 * Build with :
5 * gcc -O2 -o test_pools test_pools.c
6 * or with dlmalloc too :
7 * gcc -O2 -o test_pools -D USE_DLMALLOC test_pools.c -DUSE_DL_PREFIX dlmalloc.c
Willy Tarreauad99d292007-05-12 15:51:02 +02008 */
9
10#include <sys/time.h>
11#include <time.h>
12#include <stdlib.h>
13#include <stdbool.h>
14#include <string.h>
15#include <stdio.h>
16
17static struct timeval timeval_current(void)
18{
19 struct timeval tv;
20 gettimeofday(&tv, NULL);
21 return tv;
22}
23
24static double timeval_elapsed(struct timeval *tv)
25{
26 struct timeval tv2 = timeval_current();
27 return (tv2.tv_sec - tv->tv_sec) +
28 (tv2.tv_usec - tv->tv_usec)*1.0e-6;
29}
30
31#define torture_assert(test, expr, str) if (!(expr)) { \
32 printf("failure: %s [\n%s: Expression %s failed: %s\n]\n", \
33 test, __location__, #expr, str); \
34 return false; \
35}
36
37#define torture_assert_str_equal(test, arg1, arg2, desc) \
38 if (strcmp(arg1, arg2)) { \
39 printf("failure: %s [\n%s: Expected %s, got %s: %s\n]\n", \
40 test, __location__, arg1, arg2, desc); \
41 return false; \
42 }
43
44/* added pools from haproxy */
45#include <stdlib.h>
46
47/*
48 * Returns a pointer to an area of <__len> bytes taken from the pool <pool> or
49 * dynamically allocated. In the first case, <__pool> is updated to point to
50 * the next element in the list.
51 */
52#define pool_alloc_from(__pool, __len) \
53({ \
54 void *__p; \
55 if ((__p = (__pool)) == NULL) \
56 __p = malloc(((__len) >= sizeof (void *)) ? \
57 (__len) : sizeof(void *)); \
58 else { \
59 __pool = *(void **)(__pool); \
60 } \
61 __p; \
62})
63
64/*
65 * Puts a memory area back to the corresponding pool.
66 * Items are chained directly through a pointer that
67 * is written in the beginning of the memory area, so
68 * there's no need for any carrier cell. This implies
69 * that each memory area is at least as big as one
70 * pointer.
71 */
72#define pool_free_to(__pool, __ptr) \
73({ \
74 *(void **)(__ptr) = (void *)(__pool); \
75 __pool = (void *)(__ptr); \
76})
77
78/*
79 * Returns a pointer to type <type> taken from the
80 * pool <pool_type> or dynamically allocated. In the
81 * first case, <pool_type> is updated to point to the
82 * next element in the list.
83 */
84#define pool_alloc(type) \
85({ \
86 void *__p; \
87 if ((__p = pool_##type) == NULL) \
88 __p = malloc(sizeof_##type); \
89 else { \
90 pool_##type = *(void **)pool_##type; \
91 } \
92 __p; \
93})
94
95/*
96 * Puts a memory area back to the corresponding pool.
97 * Items are chained directly through a pointer that
98 * is written in the beginning of the memory area, so
99 * there's no need for any carrier cell. This implies
100 * that each memory area is at least as big as one
101 * pointer.
102 */
103#define pool_free(type, ptr) \
104({ \
105 *(void **)ptr = (void *)pool_##type; \
106 pool_##type = (void *)ptr; \
107})
108
109/*
110 * This function destroys a pull by freeing it completely.
111 * This should be called only under extreme circumstances.
112 */
113static inline void pool_destroy(void **pool)
114{
115 void *temp, *next;
116 next = pool;
117 while (next) {
118 temp = next;
119 next = *(void **)temp;
120 free(temp);
121 }
122}
123
124#define sizeof_talloc 1000
125
126/*
127 measure the speed of hapx versus malloc
128*/
129static bool test_speed1(void)
130{
131 void **pool_talloc = NULL;
132 void *ctx = pool_alloc(talloc);
133 unsigned count;
134 const int loop = 1000;
135 int i;
136 struct timeval tv;
137
138 printf("test: speed [\nhaproxy-pool VS MALLOC SPEED 2\n]\n");
139
140 tv = timeval_current();
141 count = 0;
142 do {
143 void *p1, *p2, *p3;
144 for (i=0;i<loop;i++) {
145 p1 = pool_alloc_from(pool_talloc, 10 + loop % 100);
146 p2 = pool_alloc_from(pool_talloc, strlen("foo bar") + 1);
147 strcpy(p2, "foo bar");
148 p3 = pool_alloc_from(pool_talloc, 300);
149 pool_free_to(pool_talloc,p1);
150 pool_free_to(pool_talloc,p3);
151 pool_free_to(pool_talloc,p2);
152 }
153 count += 3 * loop;
154 } while (timeval_elapsed(&tv) < 5.0);
155
Willy Tarreau119680b2007-05-12 16:14:55 +0200156 fprintf(stderr, "haproxy : %10.0f ops/sec\n", count/timeval_elapsed(&tv));
Willy Tarreauad99d292007-05-12 15:51:02 +0200157
158 pool_destroy(pool_talloc);
159
160 tv = timeval_current();
161 count = 0;
162 do {
163 void *p1, *p2, *p3;
164 for (i=0;i<loop;i++) {
165 p1 = malloc(10 + loop % 100);
Willy Tarreau119680b2007-05-12 16:14:55 +0200166 p2 = malloc(strlen("foo bar") + 1);
167 strcpy(p2, "foo bar");
Willy Tarreauad99d292007-05-12 15:51:02 +0200168 p3 = malloc(300);
169 free(p1);
170 free(p2);
171 free(p3);
172 }
173 count += 3 * loop;
174 } while (timeval_elapsed(&tv) < 5.0);
Willy Tarreau119680b2007-05-12 16:14:55 +0200175 fprintf(stderr, "malloc : %10.0f ops/sec\n", count/timeval_elapsed(&tv));
176
177#ifdef USE_DLMALLOC
178 tv = timeval_current();
179 count = 0;
180 do {
181 void *p1, *p2, *p3;
182 for (i=0;i<loop;i++) {
183 p1 = dlmalloc(10 + loop % 100);
184 p2 = dlmalloc(strlen("foo bar") + 1);
185 strcpy(p2, "foo bar");
186 p3 = dlmalloc(300);
187 dlfree(p1);
188 dlfree(p2);
189 dlfree(p3);
190 }
191 count += 3 * loop;
192 } while (timeval_elapsed(&tv) < 5.0);
193 fprintf(stderr, "dlmalloc: %10.0f ops/sec\n", count/timeval_elapsed(&tv));
194#endif
Willy Tarreauad99d292007-05-12 15:51:02 +0200195
196 printf("success: speed1\n");
197
198 return true;
199}
200
201int main(void)
202{
203 bool ret = test_speed1();
204 if (!ret)
205 return -1;
206 return 0;
207}