/indra/newview/llmemoryview.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 333 lines · 239 code · 49 blank · 45 comment · 26 complexity · cd4c2942450867eb007fe41a75543afb MD5 · raw file

  1. /**
  2. * @file llmemoryview.cpp
  3. * @brief LLMemoryView class implementation
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. #include "llviewerprecompiledheaders.h"
  27. #include "llmemoryview.h"
  28. #include "llappviewer.h"
  29. #include "llallocator_heap_profile.h"
  30. #include "llgl.h" // LLGLSUIDefault
  31. #include "llviewerwindow.h"
  32. #include "llviewercontrol.h"
  33. #include <sstream>
  34. #include <boost/algorithm/string/split.hpp>
  35. #include "llmemory.h"
  36. LLMemoryView::LLMemoryView(const LLMemoryView::Params& p)
  37. : LLView(p),
  38. mPaused(FALSE),
  39. //mDelay(120),
  40. mAlloc(NULL)
  41. {
  42. }
  43. LLMemoryView::~LLMemoryView()
  44. {
  45. }
  46. BOOL LLMemoryView::handleMouseDown(S32 x, S32 y, MASK mask)
  47. {
  48. if (mask & MASK_SHIFT)
  49. {
  50. }
  51. else if (mask & MASK_CONTROL)
  52. {
  53. }
  54. else
  55. {
  56. mPaused = !mPaused;
  57. }
  58. return TRUE;
  59. }
  60. BOOL LLMemoryView::handleMouseUp(S32 x, S32 y, MASK mask)
  61. {
  62. return TRUE;
  63. }
  64. BOOL LLMemoryView::handleHover(S32 x, S32 y, MASK mask)
  65. {
  66. return FALSE;
  67. }
  68. void LLMemoryView::refreshProfile()
  69. {
  70. /*
  71. LLAllocator & alloc = LLAppViewer::instance()->getAllocator();
  72. if(alloc.isProfiling()) {
  73. std::string profile_text = alloc.getRawProfile();
  74. boost::algorithm::split(mLines, profile_text, boost::bind(std::equal_to<llwchar>(), '\n', _1));
  75. } else {
  76. mLines.clear();
  77. }
  78. */
  79. if (mAlloc == NULL) {
  80. mAlloc = &LLAppViewer::instance()->getAllocator();
  81. }
  82. mLines.clear();
  83. if(mAlloc->isProfiling())
  84. {
  85. const LLAllocatorHeapProfile &prof = mAlloc->getProfile();
  86. for(size_t i = 0; i < prof.mLines.size(); ++i)
  87. {
  88. std::stringstream ss;
  89. ss << "Unfreed Mem: " << (prof.mLines[i].mLiveSize >> 20) << " M Trace: ";
  90. for(size_t k = 0; k < prof.mLines[i].mTrace.size(); ++k)
  91. {
  92. ss << LLMemType::getNameFromID(prof.mLines[i].mTrace[k]) << " ";
  93. }
  94. mLines.push_back(utf8string_to_wstring(ss.str()));
  95. }
  96. }
  97. }
  98. void LLMemoryView::draw()
  99. {
  100. const S32 UPDATE_INTERVAL = 60;
  101. const S32 MARGIN_AMT = 10;
  102. static S32 curUpdate = UPDATE_INTERVAL;
  103. static LLUIColor s_console_color = LLUIColorTable::instance().getColor("ConsoleBackground", LLColor4U::black);
  104. // setup update interval
  105. if (curUpdate >= UPDATE_INTERVAL)
  106. {
  107. refreshProfile();
  108. curUpdate = 0;
  109. }
  110. curUpdate++;
  111. // setup window properly
  112. S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
  113. S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.9f);
  114. setRect(LLRect().setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height));
  115. // setup window color
  116. F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
  117. LLColor4 color = s_console_color;
  118. color.mV[VALPHA] *= console_opacity;
  119. LLGLSUIDefault gls_ui;
  120. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  121. gl_rect_2d(0, height, width, 0, color);
  122. LLFontGL * font = LLFontGL::getFontSansSerifSmall();
  123. // draw remaining lines
  124. F32 y_pos = 0.f;
  125. F32 y_off = 0.f;
  126. F32 line_height = font->getLineHeight();
  127. S32 target_width = width - 2 * MARGIN_AMT;
  128. // cut off lines on bottom
  129. U32 max_lines = U32((height - 2 * line_height) / line_height);
  130. y_pos = height - MARGIN_AMT - line_height;
  131. y_off = 0.f;
  132. #if !MEM_TRACK_MEM
  133. std::vector<LLWString>::const_iterator end = mLines.end();
  134. if(mLines.size() > max_lines) {
  135. end = mLines.begin() + max_lines;
  136. }
  137. for (std::vector<LLWString>::const_iterator i = mLines.begin(); i != end; ++i)
  138. {
  139. font->render(*i, 0, MARGIN_AMT, y_pos - y_off,
  140. LLColor4::white,
  141. LLFontGL::LEFT,
  142. LLFontGL::BASELINE,
  143. LLFontGL::NORMAL,
  144. LLFontGL::DROP_SHADOW,
  145. S32_MAX,
  146. target_width
  147. );
  148. y_off += line_height;
  149. }
  150. #else
  151. LLMemTracker::getInstance()->preDraw(mPaused) ;
  152. {
  153. F32 x_pos = MARGIN_AMT ;
  154. U32 lines = 0 ;
  155. const char* str = LLMemTracker::getInstance()->getNextLine() ;
  156. while(str != NULL)
  157. {
  158. lines++ ;
  159. font->renderUTF8(str, 0, x_pos, y_pos - y_off,
  160. LLColor4::white,
  161. LLFontGL::LEFT,
  162. LLFontGL::BASELINE,
  163. LLFontGL::NORMAL,
  164. LLFontGL::DROP_SHADOW,
  165. S32_MAX,
  166. target_width,
  167. NULL, FALSE);
  168. str = LLMemTracker::getInstance()->getNextLine() ;
  169. y_off += line_height;
  170. if(lines >= max_lines)
  171. {
  172. lines = 0 ;
  173. x_pos += 512.f ;
  174. if(x_pos + 512.f > target_width)
  175. {
  176. break ;
  177. }
  178. y_pos = height - MARGIN_AMT - line_height;
  179. y_off = 0.f;
  180. }
  181. }
  182. }
  183. LLMemTracker::getInstance()->postDraw() ;
  184. #endif
  185. #if MEM_TRACK_TYPE
  186. S32 left, top, right, bottom;
  187. S32 x, y;
  188. S32 margin = 10;
  189. S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight();
  190. S32 xleft = margin;
  191. S32 ytop = height - margin;
  192. S32 labelwidth = 0;
  193. S32 maxmaxbytes = 1;
  194. // Make sure all timers are accounted for
  195. // Set 'MT_OTHER' to unaccounted ticks last frame
  196. {
  197. S32 display_memtypes[LLMemType::MTYPE_NUM_TYPES];
  198. for (S32 i=0; i < LLMemType::MTYPE_NUM_TYPES; i++)
  199. {
  200. display_memtypes[i] = 0;
  201. }
  202. for (S32 i=0; i < MTV_DISPLAY_NUM; i++)
  203. {
  204. S32 tidx = mtv_display_table[i].memtype;
  205. display_memtypes[tidx]++;
  206. }
  207. LLMemType::sMemCount[LLMemType::MTYPE_OTHER] = 0;
  208. LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] = 0;
  209. for (S32 tidx = 0; tidx < LLMemType::MTYPE_NUM_TYPES; tidx++)
  210. {
  211. if (display_memtypes[tidx] == 0)
  212. {
  213. LLMemType::sMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMemCount[tidx];
  214. LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMaxMemCount[tidx];
  215. }
  216. }
  217. }
  218. // Labels
  219. {
  220. y = ytop;
  221. S32 peak = 0;
  222. for (S32 i=0; i<MTV_DISPLAY_NUM; i++)
  223. {
  224. x = xleft;
  225. int tidx = mtv_display_table[i].memtype;
  226. S32 bytes = LLMemType::sMemCount[tidx];
  227. S32 maxbytes = LLMemType::sMaxMemCount[tidx];
  228. maxmaxbytes = llmax(maxbytes, maxmaxbytes);
  229. peak += maxbytes;
  230. S32 mbytes = bytes >> 20;
  231. tdesc = llformat("%s [%4d MB] in %06d NEWS",mtv_display_table[i].desc,mbytes, LLMemType::sNewCount[tidx]);
  232. LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  233. y -= (texth + 2);
  234. S32 textw = LLFontGL::getFontMonospace()->getWidth(tdesc);
  235. if (textw > labelwidth)
  236. labelwidth = textw;
  237. }
  238. S32 num_avatars = 0;
  239. S32 num_motions = 0;
  240. S32 num_loading_motions = 0;
  241. S32 num_loaded_motions = 0;
  242. S32 num_active_motions = 0;
  243. S32 num_deprecated_motions = 0;
  244. for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
  245. iter != LLCharacter::sInstances.end(); ++iter)
  246. {
  247. num_avatars++;
  248. (*iter)->getMotionController().incMotionCounts(num_motions, num_loading_motions, num_loaded_motions, num_active_motions, num_deprecated_motions);
  249. }
  250. x = xleft;
  251. tdesc = llformat("Total Bytes: %d MB Overhead: %d KB Avs %d Motions:%d Loading:%d Loaded:%d Active:%d Dep:%d",
  252. LLMemType::sTotalMem >> 20, LLMemType::sOverheadMem >> 10,
  253. num_avatars, num_motions, num_loading_motions, num_loaded_motions, num_active_motions, num_deprecated_motions);
  254. LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
  255. }
  256. // Bars
  257. y = ytop;
  258. labelwidth += 8;
  259. S32 barw = width - labelwidth - xleft - margin;
  260. for (S32 i=0; i<MTV_DISPLAY_NUM; i++)
  261. {
  262. x = xleft + labelwidth;
  263. int tidx = mtv_display_table[i].memtype;
  264. S32 bytes = LLMemType::sMemCount[tidx];
  265. F32 frac = (F32)bytes / (F32)maxmaxbytes;
  266. S32 w = (S32)(frac * (F32)barw);
  267. left = x; right = x + w;
  268. top = y; bottom = y - texth;
  269. gl_rect_2d(left, top, right, bottom, *mtv_display_table[i].color);
  270. S32 maxbytes = LLMemType::sMaxMemCount[tidx];
  271. F32 frac2 = (F32)maxbytes / (F32)maxmaxbytes;
  272. S32 w2 = (S32)(frac2 * (F32)barw);
  273. left = x + w + 1; right = x + w2;
  274. top = y; bottom = y - texth;
  275. LLColor4 tcolor = *mtv_display_table[i].color;
  276. tcolor.setAlpha(.5f);
  277. gl_rect_2d(left, top, right, bottom, tcolor);
  278. y -= (texth + 2);
  279. }
  280. dumpData();
  281. #endif
  282. LLView::draw();
  283. }