PageRenderTime 53ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcommon/llallocator_heap_profile.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 147 lines | 89 code | 25 blank | 33 comment | 35 complexity | 4fee3ea9d5adb9c3b7849fad882437bb MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llallocator_heap_profile.cpp
  3. * @brief Implementation of the parser for tcmalloc heap profile data.
  4. * @author Brad Kittenbrink
  5. *
  6. * $LicenseInfo:firstyear=2009&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "linden_common.h"
  28. #include "llallocator_heap_profile.h"
  29. #if LL_MSVC
  30. // disable warning about boost::lexical_cast returning uninitialized data
  31. // when it fails to parse the string
  32. #pragma warning (disable:4701)
  33. #pragma warning (disable:4702)
  34. #endif
  35. #include <boost/algorithm/string/split.hpp>
  36. #include <boost/bind.hpp>
  37. #include <boost/lexical_cast.hpp>
  38. #include <boost/range/iterator_range.hpp>
  39. static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:";
  40. static bool is_separator(char c)
  41. {
  42. return isspace(c) || c == '[' || c == ']' || c == ':';
  43. }
  44. void LLAllocatorHeapProfile::parse(std::string const & prof_text)
  45. {
  46. // a typedef for handling a token in the string buffer
  47. // it's a begin/end pair of string::const_iterators
  48. typedef boost::iterator_range<std::string::const_iterator> range_t;
  49. mLines.clear();
  50. if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0)
  51. {
  52. // *TODO - determine if there should be some better error state than
  53. // mLines being empty. -brad
  54. llwarns << "invalid heap profile data passed into parser." << llendl;
  55. return;
  56. }
  57. std::vector< range_t > prof_lines;
  58. std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
  59. range_t prof_range(prof_begin, prof_text.end());
  60. boost::algorithm::split(prof_lines,
  61. prof_range,
  62. boost::bind(std::equal_to<llwchar>(), '\n', _1));
  63. std::vector< range_t >::const_iterator i;
  64. for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i)
  65. {
  66. range_t const & line_text = *i;
  67. std::vector<range_t> line_elems;
  68. boost::algorithm::split(line_elems,
  69. line_text,
  70. is_separator);
  71. std::vector< range_t >::iterator j;
  72. j = line_elems.begin();
  73. while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  74. llassert_always(j != line_elems.end());
  75. U32 live_count = boost::lexical_cast<U32>(*j);
  76. ++j;
  77. while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  78. llassert_always(j != line_elems.end());
  79. U64 live_size = boost::lexical_cast<U64>(*j);
  80. ++j;
  81. while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  82. llassert_always(j != line_elems.end());
  83. U32 tot_count = boost::lexical_cast<U32>(*j);
  84. ++j;
  85. while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  86. llassert_always(j != line_elems.end());
  87. U64 tot_size = boost::lexical_cast<U64>(*j);
  88. ++j;
  89. while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  90. llassert(j != line_elems.end());
  91. if (j != line_elems.end())
  92. {
  93. ++j; // skip the '@'
  94. mLines.push_back(line(live_count, live_size, tot_count, tot_size));
  95. line & current_line = mLines.back();
  96. for(; j != line_elems.end(); ++j)
  97. {
  98. if(!j->empty())
  99. {
  100. U32 marker = boost::lexical_cast<U32>(*j);
  101. current_line.mTrace.push_back(marker);
  102. }
  103. }
  104. }
  105. }
  106. // *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
  107. }
  108. void LLAllocatorHeapProfile::dump(std::ostream & out) const
  109. {
  110. lines_t::const_iterator i;
  111. for(i = mLines.begin(); i != mLines.end(); ++i)
  112. {
  113. out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @";
  114. stack_trace::const_iterator j;
  115. for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j)
  116. {
  117. out << ' ' << *j;
  118. }
  119. out << '\n';
  120. }
  121. out.flush();
  122. }