1 /* Grab dump of Samba4 talloc tree to do benchmarks on it. */
2 #include <ccan/talloc/talloc.h>
3 #include <ccan/tal/tal.h>
4 #include <ccan/time/time.h>
5 #include <ccan/err/err.h>
6 #include <ccan/str/str.h>
20 unsigned int num_children;
21 struct node *children[0];
24 static int node_count;
26 static struct node *new_node(void)
29 return calloc(sizeof(struct node), 1);
32 /* struct db_context contains 282 bytes in 5 blocks (ref 0) d=(nil) 0x1f64e70 */
33 static struct node *parse(const char *line)
35 struct node *n = new_node();
38 p = strstr(line, " contains ");
39 p += strlen(" contains ");
40 p += strspn(line, " ");
41 n->len = strtol(p, NULL, 0);
48 static void add_child(struct node *parent, struct node *child)
51 struct node *oldp = parent;
53 parent = realloc(parent, sizeof(*parent)
54 + sizeof(parent->children[0]) * (parent->num_children+1));
55 parent->children[parent->num_children++] = child;
56 child->parent = parent;
61 /* Fix up children's parent pointers. */
62 for (i = 0; i < parent->num_children-1; i++) {
63 assert(parent->children[i]->parent == oldp);
64 parent->children[i]->parent = parent;
67 /* Fix up parent's child pointer. */
69 assert(parent->parent->children[parent->parent->num_children-1]
71 parent->parent->children[parent->parent->num_children-1]
76 /* Random string of required length */
77 static char *namelen(int len)
79 char *p = malloc(len);
80 memset(p, 'x', len-1);
85 static struct node *read_nodes(FILE *f)
88 unsigned int curr_indent = 0, indent;
89 struct node *n, *curr = new_node();
91 /* Ignore first line */
94 while (fgets(line, 4096, f)) {
97 indent = strspn(line, " ");
99 /* Ignore references for now. */
100 if (strstarts(line + indent, "reference to: "))
103 /* Blank name? Use offset of 'contains' to guess indent! */
104 if (strstarts(line + indent, "contains "))
107 is_name = strstarts(line + indent, ".name ");
109 n = parse(line + indent);
111 curr->name = namelen(n->len);
114 if (indent > curr_indent) {
115 assert(indent == curr_indent + 4);
118 /* Go back up to parent. */
119 for (curr_indent += 4;
120 curr_indent != indent;
128 while (curr->parent) {
132 assert(curr_indent == 0);
136 static int unused_talloc_destructor(void *p)
141 static void do_tallocs(struct node *node)
146 if (count++ % 16 == 0)
147 node->n = talloc_array(node->parent ? node->parent->n : NULL,
150 node->n = talloc_size(node->parent ? node->parent->n : NULL,
152 if (node->destructor)
153 talloc_set_destructor(node->n, unused_talloc_destructor);
155 talloc_set_name(node->n, "%s", node->name);
157 for (i = 0; i < node->num_children; i++)
158 do_tallocs(node->children[i]);
161 static void free_tallocs(struct node *node)
165 for (i = 0; i < node->num_children; i++)
166 free_tallocs(node->children[i]);
168 talloc_free(node->n);
171 static void unused_tal_destructor(void *p)
175 static void do_tals(struct node *node)
180 /* Tal pays a penalty for arrays, but we can't tell which is an array
181 * and which isn't. Grepping samba source gives 1221 talloc_array of
182 * 33137 talloc occurrences, so conservatively assume 1 in 16 */
183 if (count++ % 16 == 0)
184 node->n = tal_arr(node->parent ? node->parent->n : NULL,
187 node->n = tal_alloc_(node->parent ? node->parent->n : NULL,
188 node->len, false, TAL_LABEL(type, ""));
190 if (node->destructor)
191 tal_add_destructor(node->n, unused_tal_destructor);
193 tal_set_name(node->n, node->name);
195 for (i = 0; i < node->num_children; i++)
196 do_tals(node->children[i]);
199 static void free_tals(struct node *node)
203 for (i = 0; i < node->num_children; i++)
204 free_tals(node->children[i]);
209 static void do_mallocs(struct node *node)
213 node->n = malloc(node->len + (node->name ? strlen(node->name) + 1 : 1));
215 for (i = 0; i < node->num_children; i++)
216 do_mallocs(node->children[i]);
219 static void free_mallocs(struct node *node)
223 for (i = 0; i < node->num_children; i++)
224 free_mallocs(node->children[i]);
229 /* See proc(5): field 23 is vsize, 24 is rss (in pages) */
230 static void dump_vsize(void)
233 char buf[1000], *p = buf;
235 sprintf(buf, "/proc/%u/stat", getpid());
236 fd = open(buf, O_RDONLY);
237 read(fd, buf, sizeof(buf));
240 for (i = 0; i < 22; i++) {
241 p += strcspn(p, " ");
245 printf("Virtual size = %i, ", i);
246 p += strcspn(p, " ");
249 printf("RSS = %i\n", i * getpagesize());
254 int main(int argc, char *argv[])
256 struct timespec start, alloc_time, free_time;
260 bool run_talloc = true, run_tal = true, run_malloc = true;
262 f = argv[1] ? fopen(argv[1], "r") : stdin;
263 root = read_nodes(f);
265 printf("Read %u nodes\n", node_count);
268 if (streq(argv[2], "--talloc-size")) {
273 if (streq(argv[2], "--tal-size")) {
278 if (strcmp(argv[2], "--talloc") == 0)
279 run_tal = run_malloc = false;
280 else if (strcmp(argv[2], "--tal") == 0)
281 run_talloc = run_malloc = false;
282 else if (strcmp(argv[2], "--malloc") == 0)
283 run_talloc = run_tal = false;
285 errx(1, "Bad flag %s", argv[2]);
291 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
292 free_time.tv_sec = free_time.tv_nsec = 0;
293 for (i = 0; i < LOOPS; i++) {
296 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
300 free_time = time_add(free_time, time_sub(time_now(), start));
302 alloc_time = time_divide(alloc_time, i);
303 free_time = time_divide(free_time, i);
304 printf("Malloc time: %lluns\n", time_to_nsec(alloc_time));
305 printf("Free time: %lluns\n", time_to_nsec(free_time));
311 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
312 free_time.tv_sec = free_time.tv_nsec = 0;
313 for (i = 0; i < LOOPS; i++) {
316 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
320 free_time = time_add(free_time, time_sub(time_now(), start));
322 alloc_time = time_divide(alloc_time, i);
323 free_time = time_divide(free_time, i);
324 printf("Talloc time: %lluns\n", time_to_nsec(alloc_time));
325 printf("talloc_free time: %lluns\n", time_to_nsec(free_time));
327 free_time.tv_sec = free_time.tv_nsec = 0;
328 for (i = 0; i < LOOPS; i++) {
332 talloc_free(root->n);
333 free_time = time_add(free_time, time_sub(time_now(), start));
335 free_time = time_divide(free_time, i);
336 printf("Single talloc_free time: %lluns\n", time_to_nsec(free_time));
342 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
343 free_time.tv_sec = free_time.tv_nsec = 0;
344 for (i = 0; i < LOOPS; i++) {
347 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
351 free_time = time_add(free_time, time_sub(time_now(), start));
353 alloc_time = time_divide(alloc_time, i);
354 free_time = time_divide(free_time, i);
355 printf("Tal time: %lluns\n", time_to_nsec(alloc_time));
356 printf("Tal_free time: %lluns\n", time_to_nsec(free_time));
358 free_time.tv_sec = free_time.tv_nsec = 0;
359 for (i = 0; i < LOOPS; i++) {
364 free_time = time_add(free_time, time_sub(time_now(), start));
366 free_time = time_divide(free_time, i);
367 printf("Single tal_free time: %lluns\n", time_to_nsec(free_time));