xref: /dragonfly/usr.bin/flame_graph/process.c (revision d50f9ae3)
191dc43ddSMatthew Dillon /*
291dc43ddSMatthew Dillon  * Copyright (c) 2020 The DragonFly Project.  All rights reserved.
391dc43ddSMatthew Dillon  *
491dc43ddSMatthew Dillon  * This code is derived from software contributed to The DragonFly Project
591dc43ddSMatthew Dillon  * by Matthew Dillon <dillon@backplane.com>
691dc43ddSMatthew Dillon  *
791dc43ddSMatthew Dillon  * Redistribution and use in source and binary forms, with or without
891dc43ddSMatthew Dillon  * modification, are permitted provided that the following conditions
991dc43ddSMatthew Dillon  * are met:
1091dc43ddSMatthew Dillon  *
1191dc43ddSMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
1291dc43ddSMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
1391dc43ddSMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
1491dc43ddSMatthew Dillon  *    notice, this list of conditions and the following disclaimer in
1591dc43ddSMatthew Dillon  *    the documentation and/or other materials provided with the
1691dc43ddSMatthew Dillon  *    distribution.
1791dc43ddSMatthew Dillon  * 3. Neither the name of The DragonFly Project nor the names of its
1891dc43ddSMatthew Dillon  *    contributors may be used to endorse or promote products derived
1991dc43ddSMatthew Dillon  *    from this software without specific, prior written permission.
2091dc43ddSMatthew Dillon  *
2191dc43ddSMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
2291dc43ddSMatthew Dillon  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
2391dc43ddSMatthew Dillon  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
2491dc43ddSMatthew Dillon  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE
2591dc43ddSMatthew Dillon  * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
2691dc43ddSMatthew Dillon  * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
2791dc43ddSMatthew Dillon  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
2891dc43ddSMatthew Dillon  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
2991dc43ddSMatthew Dillon  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
3091dc43ddSMatthew Dillon  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
3191dc43ddSMatthew Dillon  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3291dc43ddSMatthew Dillon  * SUCH DAMAGE.
3391dc43ddSMatthew Dillon  */
3491dc43ddSMatthew Dillon 
3591dc43ddSMatthew Dillon #include "flame.h"
3691dc43ddSMatthew Dillon 
3791dc43ddSMatthew Dillon typedef struct elm {
3891dc43ddSMatthew Dillon 	struct elm *next;
3991dc43ddSMatthew Dillon 	uint64_t	hv;
4091dc43ddSMatthew Dillon 	long		ticks;
4191dc43ddSMatthew Dillon 	const char	*id;
4291dc43ddSMatthew Dillon 	size_t		idlen;
4391dc43ddSMatthew Dillon } elm_t;
4491dc43ddSMatthew Dillon 
4591dc43ddSMatthew Dillon #define MAXELM	256
4691dc43ddSMatthew Dillon #define HSIZE	(1024*1024)
4791dc43ddSMatthew Dillon #define HMASK	(HSIZE - 1)
4891dc43ddSMatthew Dillon 
4991dc43ddSMatthew Dillon static elm_t *elm_lookup(const char *s);
5091dc43ddSMatthew Dillon static void flame_process_dump(void);
5191dc43ddSMatthew Dillon 
52*d50f9ae3SSascha Wildner static long total_ticks;
5391dc43ddSMatthew Dillon 
5491dc43ddSMatthew Dillon void
flame_process_loop(void)5591dc43ddSMatthew Dillon flame_process_loop(void)
5691dc43ddSMatthew Dillon {
5791dc43ddSMatthew Dillon 	char buf[4096];
5891dc43ddSMatthew Dillon 	char *s;
5991dc43ddSMatthew Dillon 	elm_t *elm;
6091dc43ddSMatthew Dillon 	/*elm_t *elms[MAXELM];*/
6191dc43ddSMatthew Dillon 	int n;
6291dc43ddSMatthew Dillon 
6391dc43ddSMatthew Dillon 	while (fgets(buf, sizeof(buf), stdin) != NULL) {
6491dc43ddSMatthew Dillon 		n = 0;
6591dc43ddSMatthew Dillon 
6691dc43ddSMatthew Dillon 		s = strtok(buf, " \t\n\r");
6791dc43ddSMatthew Dillon 		if (s == NULL || strchr(s, '/') == NULL)
6891dc43ddSMatthew Dillon 			continue;
6991dc43ddSMatthew Dillon 		while ((s = strtok(NULL, " \t\n\r")) != NULL) {
7091dc43ddSMatthew Dillon 			elm = elm_lookup(s);
7191dc43ddSMatthew Dillon 			/*elms[n] = elm;*/
7291dc43ddSMatthew Dillon 			++elm->ticks;
7391dc43ddSMatthew Dillon 
7491dc43ddSMatthew Dillon 			if (n == MAXELM)
7591dc43ddSMatthew Dillon 				break;
7691dc43ddSMatthew Dillon 			++n;
7791dc43ddSMatthew Dillon 		}
7891dc43ddSMatthew Dillon 		++total_ticks;
7991dc43ddSMatthew Dillon 		/* more processing later */
8091dc43ddSMatthew Dillon 	}
8191dc43ddSMatthew Dillon 	flame_process_dump();
8291dc43ddSMatthew Dillon }
8391dc43ddSMatthew Dillon 
8491dc43ddSMatthew Dillon static elm_t *elm_hash_array[HSIZE];
8591dc43ddSMatthew Dillon 
8691dc43ddSMatthew Dillon static elm_t *
elm_lookup(const char * s)8791dc43ddSMatthew Dillon elm_lookup(const char *s)
8891dc43ddSMatthew Dillon {
8991dc43ddSMatthew Dillon 	size_t len;
9091dc43ddSMatthew Dillon 	uint64_t hv;
9191dc43ddSMatthew Dillon 	elm_t **scanp;
9291dc43ddSMatthew Dillon 	elm_t *scan;
9391dc43ddSMatthew Dillon 
9491dc43ddSMatthew Dillon 	if (s[0] == '0' && s[1] == 'x') {
9591dc43ddSMatthew Dillon 		hv = strtoul(s, NULL, 0);
9691dc43ddSMatthew Dillon 		if (hv < 0x8000000000000000LU)
9791dc43ddSMatthew Dillon 			s = "__userland__";
9891dc43ddSMatthew Dillon 	}
9991dc43ddSMatthew Dillon 
10091dc43ddSMatthew Dillon 	hv = 0;
10191dc43ddSMatthew Dillon 	for (len = 0; s[len] && s[len] != '+' && s[len] != '('; ++len)
10291dc43ddSMatthew Dillon 		hv = hv * 13 ^ (uint8_t)s[len];
10391dc43ddSMatthew Dillon 
10491dc43ddSMatthew Dillon 	scanp = &elm_hash_array[hv % HSIZE];
10591dc43ddSMatthew Dillon 	while ((scan = *scanp) != NULL) {
10691dc43ddSMatthew Dillon 		if (scan->hv == hv && len == scan->idlen &&
10791dc43ddSMatthew Dillon 		    bcmp(s, scan->id, len) == 0) {
10891dc43ddSMatthew Dillon 			return scan;
10991dc43ddSMatthew Dillon 		}
11091dc43ddSMatthew Dillon 		scanp = &scan->next;
11191dc43ddSMatthew Dillon 	}
11291dc43ddSMatthew Dillon 	scan = malloc(sizeof(elm_t));
11391dc43ddSMatthew Dillon 	bzero(scan, sizeof(*scan));
11491dc43ddSMatthew Dillon 	*scanp = scan;
11591dc43ddSMatthew Dillon 	scan->hv = hv;
11691dc43ddSMatthew Dillon 	scan->id = strdup(s);
11791dc43ddSMatthew Dillon 	scan->idlen = len;
11891dc43ddSMatthew Dillon 
11991dc43ddSMatthew Dillon 	return scan;
12091dc43ddSMatthew Dillon }
12191dc43ddSMatthew Dillon 
12291dc43ddSMatthew Dillon static void
flame_process_dump(void)12391dc43ddSMatthew Dillon flame_process_dump(void)
12491dc43ddSMatthew Dillon {
12591dc43ddSMatthew Dillon 	elm_t *elm;
12691dc43ddSMatthew Dillon 	int i;
12791dc43ddSMatthew Dillon 
12891dc43ddSMatthew Dillon 	for (i = 0; i < HSIZE; ++i) {
12991dc43ddSMatthew Dillon 		for (elm = elm_hash_array[i]; elm; elm = elm->next) {
13091dc43ddSMatthew Dillon 			printf("%-6ld %6.3f%% %*.*s\n",
13191dc43ddSMatthew Dillon 				elm->ticks,
13291dc43ddSMatthew Dillon 				(double)elm->ticks * 100.0 /
13391dc43ddSMatthew Dillon 				 (double)total_ticks,
13491dc43ddSMatthew Dillon 				(int)elm->idlen, (int)elm->idlen, elm->id);
13591dc43ddSMatthew Dillon 		}
13691dc43ddSMatthew Dillon 	}
13791dc43ddSMatthew Dillon }
138