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)
145 node->n = talloc_size(node->parent ? node->parent->n : NULL, node->len);
146 if (node->destructor)
147 talloc_set_destructor(node->n, unused_talloc_destructor);
149 talloc_set_name(node->n, "%s", node->name);
151 for (i = 0; i < node->num_children; i++)
152 do_tallocs(node->children[i]);
155 static void free_tallocs(struct node *node)
159 for (i = 0; i < node->num_children; i++)
160 free_tallocs(node->children[i]);
162 talloc_free(node->n);
165 static void unused_tal_destructor(void *p)
169 static void do_tals(struct node *node)
173 node->n = tal_arr(node->parent ? node->parent->n : NULL,
175 if (node->destructor)
176 tal_add_destructor(node->n, unused_tal_destructor);
178 tal_set_name(node->n, node->name);
180 for (i = 0; i < node->num_children; i++)
181 do_tals(node->children[i]);
184 static void free_tals(struct node *node)
188 for (i = 0; i < node->num_children; i++)
189 free_tals(node->children[i]);
194 static void do_mallocs(struct node *node)
198 node->n = malloc(node->len + (node->name ? strlen(node->name) + 1 : 1));
200 for (i = 0; i < node->num_children; i++)
201 do_mallocs(node->children[i]);
204 static void free_mallocs(struct node *node)
208 for (i = 0; i < node->num_children; i++)
209 free_mallocs(node->children[i]);
214 /* See proc(5): field 23 is vsize, 24 is rss (in pages) */
215 static void dump_vsize(void)
218 char buf[1000], *p = buf;
220 sprintf(buf, "/proc/%u/stat", getpid());
221 fd = open(buf, O_RDONLY);
222 read(fd, buf, sizeof(buf));
225 for (i = 0; i < 22; i++) {
226 p += strcspn(p, " ");
230 printf("Virtual size = %i, ", i);
231 p += strcspn(p, " ");
234 printf("RSS = %i\n", i * getpagesize());
239 int main(int argc, char *argv[])
241 struct timespec start, alloc_time, free_time;
245 bool run_talloc = true, run_tal = true, run_malloc = true;
247 f = argv[1] ? fopen(argv[1], "r") : stdin;
248 root = read_nodes(f);
250 printf("Read %u nodes\n", node_count);
253 if (streq(argv[2], "--talloc-size")) {
258 if (streq(argv[2], "--tal-size")) {
263 if (strcmp(argv[2], "--talloc") == 0)
264 run_tal = run_malloc = false;
265 else if (strcmp(argv[2], "--tal") == 0)
266 run_talloc = run_malloc = false;
267 else if (strcmp(argv[2], "--malloc") == 0)
268 run_talloc = run_tal = false;
270 errx(1, "Bad flag %s", argv[2]);
276 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
277 free_time.tv_sec = free_time.tv_nsec = 0;
278 for (i = 0; i < LOOPS; i++) {
281 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
285 free_time = time_add(free_time, time_sub(time_now(), start));
287 alloc_time = time_divide(alloc_time, i);
288 free_time = time_divide(free_time, i);
289 printf("Malloc time: %lluns\n", time_to_nsec(alloc_time));
290 printf("Free time: %lluns\n", time_to_nsec(free_time));
296 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
297 free_time.tv_sec = free_time.tv_nsec = 0;
298 for (i = 0; i < LOOPS; i++) {
301 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
305 free_time = time_add(free_time, time_sub(time_now(), start));
307 alloc_time = time_divide(alloc_time, i);
308 free_time = time_divide(free_time, i);
309 printf("Talloc time: %lluns\n", time_to_nsec(alloc_time));
310 printf("talloc_free time: %lluns\n", time_to_nsec(free_time));
312 free_time.tv_sec = free_time.tv_nsec = 0;
313 for (i = 0; i < LOOPS; i++) {
317 talloc_free(root->n);
318 free_time = time_add(free_time, time_sub(time_now(), start));
320 free_time = time_divide(free_time, i);
321 printf("Single talloc_free time: %lluns\n", time_to_nsec(free_time));
327 alloc_time.tv_sec = alloc_time.tv_nsec = 0;
328 free_time.tv_sec = free_time.tv_nsec = 0;
329 for (i = 0; i < LOOPS; i++) {
332 alloc_time = time_add(alloc_time, time_sub(time_now(), start));
336 free_time = time_add(free_time, time_sub(time_now(), start));
338 alloc_time = time_divide(alloc_time, i);
339 free_time = time_divide(free_time, i);
340 printf("Tal time: %lluns\n", time_to_nsec(alloc_time));
341 printf("Tal_free time: %lluns\n", time_to_nsec(free_time));
344 free_time.tv_sec = free_time.tv_nsec = 0;
345 for (i = 0; i < LOOPS; i++) {
350 free_time = time_add(free_time, time_sub(time_now(), start));
352 free_time = time_divide(free_time, i);
353 printf("Single tal_free time: %lluns\n", time_to_nsec(free_time));