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>
21 unsigned int num_children;
22 struct node *children[0];
25 static int node_count;
27 static struct node *new_node(void)
30 return calloc(sizeof(struct node), 1);
33 /* struct db_context contains 282 bytes in 5 blocks (ref 0) d=(nil) 0x1f64e70 */
34 static struct node *parse(const char *line)
36 struct node *n = new_node();
39 p = strstr(line, " contains ");
40 p += strlen(" contains ");
41 p += strspn(line, " ");
42 n->len = strtol(p, NULL, 0);
49 static void add_child(struct node *parent, struct node *child)
52 struct node *oldp = parent;
54 parent = realloc(parent, sizeof(*parent)
55 + sizeof(parent->children[0]) * (parent->num_children+1));
56 parent->children[parent->num_children++] = child;
57 child->parent = parent;
62 /* Fix up children's parent pointers. */
63 for (i = 0; i < parent->num_children-1; i++) {
64 assert(parent->children[i]->parent == oldp);
65 parent->children[i]->parent = parent;
68 /* Fix up parent's child pointer. */
70 assert(parent->parent->children[parent->parent->num_children-1]
72 parent->parent->children[parent->parent->num_children-1]
77 /* Random string of required length */
78 static char *namelen(int len)
80 char *p = malloc(len);
81 memset(p, 'x', len-1);
86 static struct node *read_nodes(FILE *f)
89 unsigned int curr_indent = 0, indent;
90 struct node *n, *curr = new_node();
92 /* Ignore first line */
95 while (fgets(line, 4096, f)) {
98 indent = strspn(line, " ");
100 /* Ignore references for now. */
101 if (strstarts(line + indent, "reference to: "))
104 /* Blank name? Use offset of 'contains' to guess indent! */
105 if (strstarts(line + indent, "contains "))
108 is_name = strstarts(line + indent, ".name ");
110 n = parse(line + indent);
112 curr->name = namelen(n->len);
115 if (indent > curr_indent) {
116 assert(indent == curr_indent + 4);
119 /* Go back up to parent. */
120 for (curr_indent += 4;
121 curr_indent != indent;
129 while (curr->parent) {
133 assert(curr_indent == 0);
137 static int unused_talloc_destructor(void *p)
142 static void do_tallocs(struct node *node)
147 if (count++ % 16 == 0)
148 node->n = talloc_array(node->parent ? node->parent->n : NULL,
151 node->n = talloc_size(node->parent ? node->parent->n : NULL,
153 if (node->destructor)
154 talloc_set_destructor(node->n, unused_talloc_destructor);
156 talloc_set_name(node->n, "%s", node->name);
158 for (i = 0; i < node->num_children; i++)
159 do_tallocs(node->children[i]);
162 static void free_tallocs(struct node *node)
166 for (i = 0; i < node->num_children; i++)
167 free_tallocs(node->children[i]);
169 talloc_free(node->n);
172 static void unused_tal_destructor(void *p)
176 static void do_tals(struct node *node)
181 node->n = tal_arr(node->parent ? node->parent->n : NULL,
184 if (node->destructor)
185 tal_add_destructor(node->n, unused_tal_destructor);
187 tal_set_name(node->n, node->name);
189 for (i = 0; i < node->num_children; i++)
190 do_tals(node->children[i]);
193 static void free_tals(struct node *node)
197 for (i = 0; i < node->num_children; i++)
198 free_tals(node->children[i]);
203 static void do_mallocs(struct node *node)
207 node->n = malloc(node->len + (node->name ? strlen(node->name) + 1 : 1));
209 for (i = 0; i < node->num_children; i++)
210 do_mallocs(node->children[i]);
213 static void free_mallocs(struct node *node)
217 for (i = 0; i < node->num_children; i++)
218 free_mallocs(node->children[i]);
223 /* See proc(5): field 23 is vsize, 24 is rss (in pages) */
224 static void dump_vsize(void)
227 char buf[1000], *p = buf;
229 sprintf(buf, "/proc/%u/stat", getpid());
230 fd = open(buf, O_RDONLY);
231 read(fd, buf, sizeof(buf));
234 for (i = 0; i < 22; i++) {
235 p += strcspn(p, " ");
239 printf("Virtual size = %i, ", i);
240 p += strcspn(p, " ");
243 printf("RSS = %i\n", i * getpagesize());
248 int main(int argc, char *argv[])
250 struct timeabs start;
251 struct timerel alloc_time, free_time;
255 bool run_talloc = true, run_tal = true, run_malloc = true;
257 f = argv[1] ? fopen(argv[1], "r") : stdin;
258 root = read_nodes(f);
260 printf("Read %u nodes\n", node_count);
263 if (streq(argv[2], "--talloc-size")) {
268 if (streq(argv[2], "--tal-size")) {
273 if (strcmp(argv[2], "--talloc") == 0)
274 run_tal = run_malloc = false;
275 else if (strcmp(argv[2], "--tal") == 0)
276 run_talloc = run_malloc = false;
277 else if (strcmp(argv[2], "--malloc") == 0)
278 run_talloc = run_tal = false;
280 errx(1, "Bad flag %s", argv[2]);
286 alloc_time.ts.tv_sec = alloc_time.ts.tv_nsec = 0;
287 free_time.ts.tv_sec = free_time.ts.tv_nsec = 0;
288 for (i = 0; i < LOOPS; i++) {
291 alloc_time = timerel_add(alloc_time,
292 time_between(time_now(), start));
296 free_time = timerel_add(free_time,
297 time_between(time_now(), start));
299 alloc_time = time_divide(alloc_time, i);
300 free_time = time_divide(free_time, i);
301 printf("Malloc time: %"PRIu64"ns\n", time_to_nsec(alloc_time));
302 printf("Free time: %"PRIu64"ns\n", time_to_nsec(free_time));
308 alloc_time.ts.tv_sec = alloc_time.ts.tv_nsec = 0;
309 free_time.ts.tv_sec = free_time.ts.tv_nsec = 0;
310 for (i = 0; i < LOOPS; i++) {
313 alloc_time = timerel_add(alloc_time,
314 time_between(time_now(), start));
318 free_time = timerel_add(free_time,
319 time_between(time_now(), start));
321 alloc_time = time_divide(alloc_time, i);
322 free_time = time_divide(free_time, i);
323 printf("Talloc time: %"PRIu64"ns\n", time_to_nsec(alloc_time));
324 printf("talloc_free time: %"PRIu64"ns\n", time_to_nsec(free_time));
326 free_time.ts.tv_sec = free_time.ts.tv_nsec = 0;
327 for (i = 0; i < LOOPS; i++) {
331 talloc_free(root->n);
332 free_time = timerel_add(free_time,
333 time_between(time_now(), start));
335 free_time = time_divide(free_time, i);
336 printf("Single talloc_free time: %"PRIu64"\n", time_to_nsec(free_time));
342 alloc_time.ts.tv_sec = alloc_time.ts.tv_nsec = 0;
343 free_time.ts.tv_sec = free_time.ts.tv_nsec = 0;
344 for (i = 0; i < LOOPS; i++) {
347 alloc_time = timerel_add(alloc_time,
348 time_between(time_now(), start));
352 free_time = timerel_add(free_time,
353 time_between(time_now(), start));
355 alloc_time = time_divide(alloc_time, i);
356 free_time = time_divide(free_time, i);
357 printf("Tal time: %"PRIu64"ns\n", time_to_nsec(alloc_time));
358 printf("Tal_free time: %"PRIu64"ns\n", time_to_nsec(free_time));
360 free_time.ts.tv_sec = free_time.ts.tv_nsec = 0;
361 for (i = 0; i < LOOPS; i++) {
366 free_time = timerel_add(free_time,
367 time_between(time_now(), start));
369 free_time = time_divide(free_time, i);
370 printf("Single tal_free time: %"PRIu64"ns\n", time_to_nsec(free_time));