1 /* 2 * Copyright (c) 2020 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "flame.h" 36 37 typedef struct elm { 38 struct elm *next; 39 uint64_t hv; 40 long ticks; 41 const char *id; 42 size_t idlen; 43 } elm_t; 44 45 #define MAXELM 256 46 #define HSIZE (1024*1024) 47 #define HMASK (HSIZE - 1) 48 49 static elm_t *elm_lookup(const char *s); 50 static void flame_process_dump(void); 51 52 static long total_ticks; 53 54 void 55 flame_process_loop(void) 56 { 57 char buf[4096]; 58 char *s; 59 elm_t *elm; 60 /*elm_t *elms[MAXELM];*/ 61 int n; 62 63 while (fgets(buf, sizeof(buf), stdin) != NULL) { 64 n = 0; 65 66 s = strtok(buf, " \t\n\r"); 67 if (s == NULL || strchr(s, '/') == NULL) 68 continue; 69 while ((s = strtok(NULL, " \t\n\r")) != NULL) { 70 elm = elm_lookup(s); 71 /*elms[n] = elm;*/ 72 ++elm->ticks; 73 74 if (n == MAXELM) 75 break; 76 ++n; 77 } 78 ++total_ticks; 79 /* more processing later */ 80 } 81 flame_process_dump(); 82 } 83 84 static elm_t *elm_hash_array[HSIZE]; 85 86 static elm_t * 87 elm_lookup(const char *s) 88 { 89 size_t len; 90 uint64_t hv; 91 elm_t **scanp; 92 elm_t *scan; 93 94 if (s[0] == '0' && s[1] == 'x') { 95 hv = strtoul(s, NULL, 0); 96 if (hv < 0x8000000000000000LU) 97 s = "__userland__"; 98 } 99 100 hv = 0; 101 for (len = 0; s[len] && s[len] != '+' && s[len] != '('; ++len) 102 hv = hv * 13 ^ (uint8_t)s[len]; 103 104 scanp = &elm_hash_array[hv % HSIZE]; 105 while ((scan = *scanp) != NULL) { 106 if (scan->hv == hv && len == scan->idlen && 107 bcmp(s, scan->id, len) == 0) { 108 return scan; 109 } 110 scanp = &scan->next; 111 } 112 scan = malloc(sizeof(elm_t)); 113 bzero(scan, sizeof(*scan)); 114 *scanp = scan; 115 scan->hv = hv; 116 scan->id = strdup(s); 117 scan->idlen = len; 118 119 return scan; 120 } 121 122 static void 123 flame_process_dump(void) 124 { 125 elm_t *elm; 126 int i; 127 128 for (i = 0; i < HSIZE; ++i) { 129 for (elm = elm_hash_array[i]; elm; elm = elm->next) { 130 printf("%-6ld %6.3f%% %*.*s\n", 131 elm->ticks, 132 (double)elm->ticks * 100.0 / 133 (double)total_ticks, 134 (int)elm->idlen, (int)elm->idlen, elm->id); 135 } 136 } 137 } 138