]> git.ipfire.org Git - thirdparty/pdns.git/blob - pdns/malloctrace.cc
Merge pull request #2923 from pieterlexis/pipe-backend-fixes
[thirdparty/pdns.git] / pdns / malloctrace.cc
1 #include "malloctrace.hh"
2 #include <sstream>
3 #include <algorithm>
4
5 using std::string;
6 using std::map;
7 using std::vector;
8
9 MallocTracer* g_mtracer;
10
11 #if 1
12 #include <execinfo.h>
13 vector<void*> MallocTracer::makeBacktrace()
14 {
15 void *array[20]; //only care about last 17 functions (3 taken with tracing support)
16 size_t size = backtrace (array, 20);
17 return vector<void*>(array, array+size);
18 }
19
20
21 extern "C" {
22 extern void *__libc_malloc(size_t size);
23 extern void __libc_free(void* ptr);
24
25 void* malloc (size_t size)
26 {
27 if(!g_mtracer) {
28 void *mem = __libc_malloc(sizeof(MallocTracer));
29 g_mtracer = new(mem) MallocTracer;
30 }
31 return g_mtracer->malloc(size);
32 }
33
34 void free(void* ptr)
35 {
36 if(ptr)
37 g_mtracer->free(ptr);
38 }
39 }
40
41 #endif
42
43 static thread_local bool l_active;
44 void* MallocTracer::malloc(size_t size)
45 {
46 void* ret = __libc_malloc(size);
47 if(!l_active) {
48 l_active=true;
49
50 d_allocflux+=size;
51 d_allocs++;
52 d_totAllocated += size;
53
54
55 std::lock_guard<std::mutex> lock(d_mut);
56 auto& ent=d_stats[makeBacktrace()];
57 ent.count++;
58 ent.sizes[size]++;
59 d_sizes[ret]=size;
60
61 l_active=false;
62 }
63 return ret;
64 }
65
66 void MallocTracer::free(void* ptr)
67 {
68 __libc_free(ptr);
69 if(!l_active) {
70 l_active=true;
71 std::lock_guard<std::mutex> lock(d_mut);
72 auto f = d_sizes.find(ptr);
73 if(f != d_sizes.end()) {
74 d_totAllocated -= f->second;
75 d_sizes.erase(f);
76 }
77 l_active=false;
78 }
79 }
80
81 MallocTracer::allocators_t MallocTracer::topAllocators(int num)
82 {
83 l_active=true;
84 allocators_t ret;
85 for(const auto& e : d_stats) {
86 ret.push_back(make_pair(e.second, e.first));
87 }
88 std::sort(ret.begin(), ret.end(),
89 [](const allocators_t::value_type& a,
90 const allocators_t::value_type& b) {
91 return a.first.count < b.first.count;
92 });
93 if(num > 0)
94 ret.erase(ret.begin(), ret.begin() + (ret.size() - num));
95 l_active=false;
96 return ret;
97 }
98
99 std::string MallocTracer::topAllocatorsString(int num)
100 {
101 l_active=true;
102 auto raw = topAllocators(num);
103 l_active=true;
104 std::ostringstream ret;
105 for(const auto& e : raw) {
106 ret<<"Called "<<e.first.count<<" times\n";
107 for(const auto& u : e.first.sizes)
108 ret<<u.first<<"b: "<<u.second<<" times, ";
109 ret<<'\n';
110 char** strings = backtrace_symbols(&e.second[0], e.second.size());
111 for(unsigned int i=0; i < e.second.size(); ++i)
112 ret<<strings[i]<<'\n';
113 ret<<"-----\n";
114 }
115
116 string str =ret.str();
117 l_active=false;
118 return str;
119 }
120
121 /*
122 char **strings;
123 size_t i;
124 strings = backtrace_symbols (array, size); //Need -rdynamic gcc (linker) flag for this to work
125
126 for (i = 0; i < size; i++) //skip useless functions
127 ret+=strings[i]+string("\n");
128 return ret;
129 */
130