| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #define PULSE_INTERNALS 1 |
| 4 | #include "pulse-trace-allocations.h" |
| 5 | |
| 6 | #ifdef NETDATA_TRACE_ALLOCATIONS |
| 7 | |
| 8 | struct memory_trace_data { |
| 9 | RRDSET *st_memory; |
| 10 | RRDSET *st_allocations; |
| 11 | RRDSET *st_avg_alloc; |
| 12 | RRDSET *st_ops; |
| 13 | }; |
| 14 | |
| 15 | static int do_memory_trace_item(void *item, void *data) { |
| 16 | struct memory_trace_data *tmp = data; |
| 17 | struct malloc_trace *p = item; |
| 18 | |
| 19 | // ------------------------------------------------------------------------ |
| 20 | |
| 21 | if(!p->rd_bytes) |
| 22 | p->rd_bytes = rrddim_add(tmp->st_memory, p->function, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); |
| 23 | |
| 24 | collected_number bytes = (collected_number)__atomic_load_n(&p->bytes, __ATOMIC_RELAXED); |
| 25 | rrddim_set_by_pointer(tmp->st_memory, p->rd_bytes, bytes); |
| 26 | |
| 27 | // ------------------------------------------------------------------------ |
| 28 | |
| 29 | if(!p->rd_allocations) |
| 30 | p->rd_allocations = rrddim_add(tmp->st_allocations, p->function, NULL, 1, 1, RRD_ALGORITHM_ABSOLUTE); |
| 31 | |
| 32 | collected_number allocs = (collected_number)__atomic_load_n(&p->allocations, __ATOMIC_RELAXED); |
| 33 | rrddim_set_by_pointer(tmp->st_allocations, p->rd_allocations, allocs); |
| 34 | |
| 35 | // ------------------------------------------------------------------------ |
| 36 | |
| 37 | if(!p->rd_avg_alloc) |
| 38 | p->rd_avg_alloc = rrddim_add(tmp->st_avg_alloc, p->function, NULL, 1, 100, RRD_ALGORITHM_ABSOLUTE); |
| 39 | |
| 40 | collected_number avg_alloc = (allocs)?(bytes * 100 / allocs):0; |
| 41 | rrddim_set_by_pointer(tmp->st_avg_alloc, p->rd_avg_alloc, avg_alloc); |
| 42 | |
| 43 | // ------------------------------------------------------------------------ |
| 44 | |
| 45 | if(!p->rd_ops) |
| 46 | p->rd_ops = rrddim_add(tmp->st_ops, p->function, NULL, 1, 1, RRD_ALGORITHM_INCREMENTAL); |
| 47 | |
| 48 | collected_number ops = 0; |
| 49 | ops += (collected_number)__atomic_load_n(&p->malloc_calls, __ATOMIC_RELAXED); |
| 50 | ops += (collected_number)__atomic_load_n(&p->calloc_calls, __ATOMIC_RELAXED); |
| 51 | ops += (collected_number)__atomic_load_n(&p->realloc_calls, __ATOMIC_RELAXED); |
| 52 | ops += (collected_number)__atomic_load_n(&p->strdup_calls, __ATOMIC_RELAXED); |
| 53 | ops += (collected_number)__atomic_load_n(&p->free_calls, __ATOMIC_RELAXED); |
| 54 | rrddim_set_by_pointer(tmp->st_ops, p->rd_ops, ops); |
| 55 | |
| 56 | // ------------------------------------------------------------------------ |
| 57 | |
| 58 | return 1; |
| 59 | } |
| 60 | |
| 61 | void pulse_trace_allocations_do(bool extended) { |
| 62 | if(!extended) return; |
| 63 | |
| 64 | static struct memory_trace_data tmp = { |
| 65 | .st_memory = NULL, |
| 66 | .st_allocations = NULL, |
| 67 | .st_avg_alloc = NULL, |
| 68 | .st_ops = NULL, |
| 69 | }; |
| 70 | |
| 71 | if(!tmp.st_memory) { |
| 72 | tmp.st_memory = rrdset_create_localhost( |
| 73 | "netdata" |
| 74 | , "memory_size" |
| 75 | , NULL |
| 76 | , "memory" |
| 77 | , "netdata.memory.size" |
| 78 | , "Netdata Memory Used by Function" |
| 79 | , "bytes" |
| 80 | , "netdata" |
| 81 | , "pulse" |
| 82 | , 900000 |
| 83 | , localhost->rrd_update_every |
| 84 | , RRDSET_TYPE_STACKED |
| 85 | ); |
| 86 | } |
| 87 | |
| 88 | if(!tmp.st_ops) { |
| 89 | tmp.st_ops = rrdset_create_localhost( |
| 90 | "netdata" |
| 91 | , "memory_operations" |
| 92 | , NULL |
| 93 | , "memory" |
| 94 | , "netdata.memory.operations" |
| 95 | , "Netdata Memory Operations by Function" |
| 96 | , "ops/s" |
| 97 | , "netdata" |
| 98 | , "pulse" |
| 99 | , 900001 |
| 100 | , localhost->rrd_update_every |
| 101 | , RRDSET_TYPE_LINE |
| 102 | ); |
| 103 | } |
| 104 | |
| 105 | if(!tmp.st_allocations) { |
| 106 | tmp.st_allocations = rrdset_create_localhost( |
| 107 | "netdata" |
| 108 | , "memory_allocations" |
| 109 | , NULL |
| 110 | , "memory" |
| 111 | , "netdata.memory.allocations" |
| 112 | , "Netdata Memory Allocations by Function" |
| 113 | , "allocations" |
| 114 | , "netdata" |
| 115 | , "pulse" |
| 116 | , 900002 |
| 117 | , localhost->rrd_update_every |
| 118 | , RRDSET_TYPE_STACKED |
| 119 | ); |
| 120 | } |
| 121 | |
| 122 | if(!tmp.st_avg_alloc) { |
| 123 | tmp.st_avg_alloc = rrdset_create_localhost( |
| 124 | "netdata" |
| 125 | , "memory_avg_alloc" |
| 126 | , NULL |
| 127 | , "memory" |
| 128 | , "netdata.memory.avg_alloc" |
| 129 | , "Netdata Average Allocation Size by Function" |
| 130 | , "bytes" |
| 131 | , "netdata" |
| 132 | , "pulse" |
| 133 | , 900003 |
| 134 | , localhost->rrd_update_every |
| 135 | , RRDSET_TYPE_LINE |
| 136 | ); |
| 137 | } |
| 138 | |
| 139 | malloc_trace_walkthrough(do_memory_trace_item, &tmp); |
| 140 | |
| 141 | rrdset_done(tmp.st_memory); |
| 142 | rrdset_done(tmp.st_ops); |
| 143 | rrdset_done(tmp.st_allocations); |
| 144 | rrdset_done(tmp.st_avg_alloc); |
| 145 | } |
| 146 | |
| 147 | #endif |