llallocator_heap_profile.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:5k
源码类别:

游戏引擎

开发平台:

C++ Builder

  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=viewergpl$
  7.  * 
  8.  * Copyright (c) 2009-2010, Linden Research, Inc.
  9.  * 
  10.  * Second Life Viewer Source Code
  11.  * The source code in this file ("Source Code") is provided by Linden Lab
  12.  * to you under the terms of the GNU General Public License, version 2.0
  13.  * ("GPL"), unless you have obtained a separate licensing agreement
  14.  * ("Other License"), formally executed by you and Linden Lab.  Terms of
  15.  * the GPL can be found in doc/GPL-license.txt in this distribution, or
  16.  * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  17.  * 
  18.  * There are special exceptions to the terms and conditions of the GPL as
  19.  * it is applied to this Source Code. View the full text of the exception
  20.  * in the file doc/FLOSS-exception.txt in this software distribution, or
  21.  * online at
  22.  * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  23.  * 
  24.  * By copying, modifying or distributing this software, you acknowledge
  25.  * that you have read and understood your obligations described above,
  26.  * and agree to abide by those obligations.
  27.  * 
  28.  * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  29.  * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  30.  * COMPLETENESS OR PERFORMANCE.
  31.  * $/LicenseInfo$
  32.  */
  33. #include "linden_common.h"
  34. #include "llallocator_heap_profile.h"
  35. #if LL_MSVC
  36. // disable warning about boost::lexical_cast returning uninitialized data
  37. // when it fails to parse the string
  38. #pragma warning (disable:4701)
  39. #pragma warning (disable:4702)
  40. #endif
  41. #include <boost/algorithm/string/split.hpp>
  42. #include <boost/bind.hpp>
  43. #include <boost/lexical_cast.hpp>
  44. #include <boost/range/iterator_range.hpp>
  45. static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:";
  46. static bool is_separator(char c)
  47. {
  48.     return isspace(c) || c == '[' || c == ']' || c == ':';
  49. }
  50. void LLAllocatorHeapProfile::parse(std::string const & prof_text)
  51. {
  52.     // a typedef for handling a token in the string buffer
  53.     // it's a begin/end pair of string::const_iterators
  54.     typedef boost::iterator_range<std::string::const_iterator> range_t;
  55.     mLines.clear();
  56.     if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0)
  57.     {
  58.         // *TODO - determine if there should be some better error state than
  59.         // mLines being empty. -brad
  60.         llwarns << "invalid heap profile data passed into parser." << llendl;
  61.         return;
  62.     }
  63.     std::vector< range_t > prof_lines;
  64.     std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length();
  65. range_t prof_range(prof_begin, prof_text.end());
  66.     boost::algorithm::split(prof_lines,
  67.         prof_range,
  68.         boost::bind(std::equal_to<llwchar>(), 'n', _1));
  69.     std::vector< range_t >::const_iterator i;
  70.     for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i)
  71.     {
  72.         range_t const & line_text = *i;
  73.         std::vector<range_t> line_elems;
  74.         boost::algorithm::split(line_elems,
  75.             line_text,
  76.             is_separator);
  77.         std::vector< range_t >::iterator j;
  78.         j = line_elems.begin();
  79.         while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  80.         llassert_always(j != line_elems.end());
  81.         U32 live_count = boost::lexical_cast<U32>(*j);
  82.         ++j;
  83.         while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  84.         llassert_always(j != line_elems.end());
  85.         U64 live_size = boost::lexical_cast<U64>(*j);
  86.         ++j;
  87.         while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  88.         llassert_always(j != line_elems.end());
  89.         U32 tot_count = boost::lexical_cast<U32>(*j);
  90.         ++j;
  91.         while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  92.         llassert_always(j != line_elems.end());
  93.         U64 tot_size = boost::lexical_cast<U64>(*j);
  94.         ++j;
  95.         while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens
  96. llassert(j != line_elems.end());
  97.         if (j != line_elems.end())
  98. {
  99. ++j; // skip the '@'
  100. mLines.push_back(line(live_count, live_size, tot_count, tot_size));
  101. line & current_line = mLines.back();
  102. for(; j != line_elems.end(); ++j)
  103. {
  104. if(!j->empty())
  105. {
  106. U32 marker = boost::lexical_cast<U32>(*j);
  107. current_line.mTrace.push_back(marker);
  108. }
  109. }
  110. }
  111.     }
  112.     // *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it
  113. }
  114. void LLAllocatorHeapProfile::dump(std::ostream & out) const
  115. {
  116.     lines_t::const_iterator i;
  117.     for(i = mLines.begin(); i != mLines.end(); ++i)
  118.     {
  119.         out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @";
  120.         stack_trace::const_iterator j;
  121.         for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j)
  122.         {
  123.             out << ' ' << *j;
  124.         }
  125.         out << 'n';
  126.     }
  127.     out.flush();
  128. }