You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

152 lines
3.5 KiB

  1. /*
  2. * This file is part of PowerDNS or dnsdist.
  3. * Copyright -- PowerDNS.COM B.V. and its contributors
  4. *
  5. * This program is free software; you can redistribute it and/or modify
  6. * it under the terms of version 2 of the GNU General Public License as
  7. * published by the Free Software Foundation.
  8. *
  9. * In addition, for the avoidance of any doubt, permission is granted to
  10. * link this program with OpenSSL and to (re)distribute the binaries
  11. * produced as the result of such linking.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, write to the Free Software
  20. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  21. */
  22. #include "malloctrace.hh"
  23. #include <sstream>
  24. #include <algorithm>
  25. using std::string;
  26. using std::map;
  27. using std::vector;
  28. MallocTracer* g_mtracer;
  29. #if 1
  30. #include <execinfo.h>
  31. vector<void*> MallocTracer::makeBacktrace()
  32. {
  33. void *array[20]; //only care about last 17 functions (3 taken with tracing support)
  34. size_t size = backtrace (array, 20);
  35. return vector<void*>(array, array+size);
  36. }
  37. extern "C" {
  38. extern void *__libc_malloc(size_t size);
  39. extern void __libc_free(void* ptr);
  40. void* malloc (size_t size)
  41. {
  42. if(!g_mtracer) {
  43. void *mem = __libc_malloc(sizeof(MallocTracer));
  44. g_mtracer = new(mem) MallocTracer;
  45. }
  46. return g_mtracer->malloc(size);
  47. }
  48. void free(void* ptr)
  49. {
  50. if(ptr)
  51. g_mtracer->free(ptr);
  52. }
  53. }
  54. #endif
  55. static thread_local bool l_active;
  56. void* MallocTracer::malloc(size_t size)
  57. {
  58. void* ret = __libc_malloc(size);
  59. if(!l_active) {
  60. l_active=true;
  61. d_allocflux+=size;
  62. d_allocs++;
  63. d_totAllocated += size;
  64. std::lock_guard<std::mutex> lock(d_mut);
  65. auto& ent=d_stats[makeBacktrace()];
  66. ent.count++;
  67. ent.sizes[size]++;
  68. d_sizes[ret]=size;
  69. l_active=false;
  70. }
  71. return ret;
  72. }
  73. void MallocTracer::free(void* ptr)
  74. {
  75. __libc_free(ptr);
  76. if(!l_active) {
  77. l_active=true;
  78. std::lock_guard<std::mutex> lock(d_mut);
  79. auto f = d_sizes.find(ptr);
  80. if(f != d_sizes.end()) {
  81. d_totAllocated -= f->second;
  82. d_sizes.erase(f);
  83. }
  84. l_active=false;
  85. }
  86. }
  87. MallocTracer::allocators_t MallocTracer::topAllocators(int num)
  88. {
  89. l_active=true;
  90. allocators_t ret;
  91. for(const auto& e : d_stats) {
  92. ret.push_back(make_pair(e.second, e.first));
  93. }
  94. std::sort(ret.begin(), ret.end(),
  95. [](const allocators_t::value_type& a,
  96. const allocators_t::value_type& b) {
  97. return a.first.count < b.first.count;
  98. });
  99. if((unsigned int)num > ret.size())
  100. ret.clear();
  101. else if(num > 0)
  102. ret.erase(ret.begin(), ret.begin() + (ret.size() - num));
  103. l_active=false;
  104. return ret;
  105. }
  106. std::string MallocTracer::topAllocatorsString(int num)
  107. {
  108. l_active=true;
  109. auto raw = topAllocators(num);
  110. l_active=true;
  111. std::ostringstream ret;
  112. for(const auto& e : raw) {
  113. ret<<"Called "<<e.first.count<<" times\n";
  114. for(const auto& u : e.first.sizes)
  115. ret<<u.first<<"b: "<<u.second<<" times, ";
  116. ret<<'\n';
  117. char** strings = backtrace_symbols(&e.second[0], e.second.size());
  118. for(unsigned int i=0; i < e.second.size(); ++i)
  119. ret<<strings[i]<<'\n';
  120. ret<<"-----\n";
  121. }
  122. string str =ret.str();
  123. l_active=false;
  124. return str;
  125. }
  126. void MallocTracer::clearAllocators()
  127. {
  128. l_active=true;
  129. std::lock_guard<std::mutex> lock(d_mut);
  130. d_stats.clear();
  131. l_active=false;
  132. }