PageRenderTime 426ms CodeModel.GetById 121ms app.highlight 136ms RepoModel.GetById 165ms app.codeStats 1ms

/indra/newview/llmemoryview.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 333 lines | 239 code | 49 blank | 45 comment | 25 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
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llmemoryview.h"
 30
 31#include "llappviewer.h"
 32#include "llallocator_heap_profile.h"
 33#include "llgl.h"						// LLGLSUIDefault
 34#include "llviewerwindow.h"
 35#include "llviewercontrol.h"
 36
 37#include <sstream>
 38#include <boost/algorithm/string/split.hpp>
 39
 40#include "llmemory.h"
 41
 42LLMemoryView::LLMemoryView(const LLMemoryView::Params& p)
 43:	LLView(p),
 44	mPaused(FALSE),
 45	//mDelay(120),
 46    mAlloc(NULL)
 47{
 48}
 49
 50LLMemoryView::~LLMemoryView()
 51{
 52}
 53
 54BOOL LLMemoryView::handleMouseDown(S32 x, S32 y, MASK mask)
 55{
 56	if (mask & MASK_SHIFT)
 57	{
 58	}
 59	else if (mask & MASK_CONTROL)
 60	{
 61	}
 62	else
 63	{
 64		mPaused = !mPaused;
 65	}
 66	return TRUE;
 67}
 68
 69BOOL LLMemoryView::handleMouseUp(S32 x, S32 y, MASK mask)
 70{
 71	return TRUE;
 72}
 73
 74
 75BOOL LLMemoryView::handleHover(S32 x, S32 y, MASK mask)
 76{
 77	return FALSE;
 78}
 79
 80void LLMemoryView::refreshProfile()
 81{
 82	/*
 83    LLAllocator & alloc = LLAppViewer::instance()->getAllocator();
 84    if(alloc.isProfiling()) {
 85        std::string profile_text = alloc.getRawProfile();
 86
 87        boost::algorithm::split(mLines, profile_text, boost::bind(std::equal_to<llwchar>(), '\n', _1));
 88    } else {
 89        mLines.clear();
 90    }
 91	*/
 92    if (mAlloc == NULL) {
 93        mAlloc = &LLAppViewer::instance()->getAllocator();
 94    }
 95
 96	mLines.clear();
 97
 98 	if(mAlloc->isProfiling()) 
 99	{
100		const LLAllocatorHeapProfile &prof = mAlloc->getProfile();
101		for(size_t i = 0; i < prof.mLines.size(); ++i)
102		{
103			std::stringstream ss;
104			ss << "Unfreed Mem: " << (prof.mLines[i].mLiveSize >> 20) << " M     Trace: ";
105			for(size_t k = 0; k < prof.mLines[i].mTrace.size(); ++k)
106			{
107				ss << LLMemType::getNameFromID(prof.mLines[i].mTrace[k]) << "  ";
108			}
109			mLines.push_back(utf8string_to_wstring(ss.str()));
110		}
111	}
112}
113
114void LLMemoryView::draw()
115{
116	const S32 UPDATE_INTERVAL = 60;
117	const S32 MARGIN_AMT = 10; 
118	static S32 curUpdate = UPDATE_INTERVAL;
119    static LLUIColor s_console_color = LLUIColorTable::instance().getColor("ConsoleBackground", LLColor4U::black);	
120
121	// setup update interval
122	if (curUpdate >= UPDATE_INTERVAL)
123	{
124		refreshProfile();
125		curUpdate = 0;
126	}
127	curUpdate++;
128
129	// setup window properly
130	S32 height = (S32) (gViewerWindow->getWindowRectScaled().getHeight()*0.75f);
131	S32 width = (S32) (gViewerWindow->getWindowRectScaled().getWidth() * 0.9f);
132	setRect(LLRect().setLeftTopAndSize(getRect().mLeft, getRect().mTop, width, height));
133	
134	// setup window color
135	F32 console_opacity = llclamp(gSavedSettings.getF32("ConsoleBackgroundOpacity"), 0.f, 1.f);
136	LLColor4 color = s_console_color;
137	color.mV[VALPHA] *= console_opacity;
138
139	LLGLSUIDefault gls_ui;
140	gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
141	gl_rect_2d(0, height, width, 0, color);
142	
143    LLFontGL * font = LLFontGL::getFontSansSerifSmall(); 
144
145	// draw remaining lines
146	F32 y_pos = 0.f;
147    F32 y_off = 0.f;
148
149	F32 line_height = font->getLineHeight();
150    S32 target_width = width - 2 * MARGIN_AMT;
151
152	// cut off lines on bottom
153	U32 max_lines = U32((height - 2 * line_height) / line_height);
154	y_pos = height - MARGIN_AMT - line_height;
155    y_off = 0.f;
156
157#if !MEM_TRACK_MEM
158	std::vector<LLWString>::const_iterator end = mLines.end();
159    if(mLines.size() > max_lines) {
160        end = mLines.begin() + max_lines;
161    }
162    for (std::vector<LLWString>::const_iterator i = mLines.begin(); i != end; ++i)
163	{
164		font->render(*i, 0, MARGIN_AMT, y_pos -  y_off,
165            LLColor4::white,
166			LLFontGL::LEFT, 
167			LLFontGL::BASELINE,
168            LLFontGL::NORMAL,
169			LLFontGL::DROP_SHADOW,
170			S32_MAX,
171			target_width
172			);
173		y_off += line_height;
174	}
175
176#else
177	LLMemTracker::getInstance()->preDraw(mPaused) ;
178
179	{
180		F32 x_pos = MARGIN_AMT ;
181		U32 lines = 0 ;
182		const char* str = LLMemTracker::getInstance()->getNextLine() ;
183		while(str != NULL)
184		{
185			lines++ ;
186			font->renderUTF8(str, 0, x_pos, y_pos -  y_off,
187				LLColor4::white,
188				LLFontGL::LEFT, 
189				LLFontGL::BASELINE,
190				LLFontGL::NORMAL,
191				LLFontGL::DROP_SHADOW,
192				S32_MAX,
193				target_width,
194				NULL, FALSE);
195		
196			str = LLMemTracker::getInstance()->getNextLine() ;
197			y_off += line_height;
198
199			if(lines >= max_lines)
200			{
201				lines = 0 ;
202				x_pos += 512.f ;
203				if(x_pos + 512.f > target_width)
204				{
205					break ;
206				}
207
208				y_pos = height - MARGIN_AMT - line_height;
209				y_off = 0.f;
210			}
211		}
212	}
213
214	LLMemTracker::getInstance()->postDraw() ;
215#endif
216
217#if MEM_TRACK_TYPE
218
219	S32 left, top, right, bottom;
220	S32 x, y;
221
222	S32 margin = 10;
223	S32 texth = (S32)LLFontGL::getFontMonospace()->getLineHeight();
224
225	S32 xleft = margin;
226	S32 ytop = height - margin;
227	S32 labelwidth = 0;
228	S32 maxmaxbytes = 1;
229
230	// Make sure all timers are accounted for
231	// Set 'MT_OTHER' to unaccounted ticks last frame
232	{
233		S32 display_memtypes[LLMemType::MTYPE_NUM_TYPES];
234		for (S32 i=0; i < LLMemType::MTYPE_NUM_TYPES; i++)
235		{
236			display_memtypes[i] = 0;
237		}
238		for (S32 i=0; i < MTV_DISPLAY_NUM; i++)
239		{
240			S32 tidx = mtv_display_table[i].memtype;
241			display_memtypes[tidx]++;
242		}
243		LLMemType::sMemCount[LLMemType::MTYPE_OTHER] = 0;
244		LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] = 0;
245		for (S32 tidx = 0; tidx < LLMemType::MTYPE_NUM_TYPES; tidx++)
246		{
247			if (display_memtypes[tidx] == 0)
248			{
249				LLMemType::sMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMemCount[tidx];
250				LLMemType::sMaxMemCount[LLMemType::MTYPE_OTHER] += LLMemType::sMaxMemCount[tidx];
251			}
252		}
253	}
254	
255	// Labels
256	{
257		y = ytop;
258		S32 peak = 0;
259		for (S32 i=0; i<MTV_DISPLAY_NUM; i++)
260		{
261			x = xleft;
262
263			int tidx = mtv_display_table[i].memtype;
264			S32 bytes = LLMemType::sMemCount[tidx];
265			S32 maxbytes = LLMemType::sMaxMemCount[tidx];
266			maxmaxbytes = llmax(maxbytes, maxmaxbytes);
267			peak += maxbytes;
268			S32 mbytes = bytes >> 20;
269
270			tdesc = llformat("%s [%4d MB] in %06d NEWS",mtv_display_table[i].desc,mbytes, LLMemType::sNewCount[tidx]);
271			LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
272			
273			y -= (texth + 2);
274
275			S32 textw = LLFontGL::getFontMonospace()->getWidth(tdesc);
276			if (textw > labelwidth)
277				labelwidth = textw;
278		}
279
280		S32 num_avatars = 0;
281		S32 num_motions = 0;
282		S32 num_loading_motions = 0;
283		S32 num_loaded_motions = 0;
284		S32 num_active_motions = 0;
285		S32 num_deprecated_motions = 0;
286		for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin();
287			 iter != LLCharacter::sInstances.end(); ++iter)
288		{
289			num_avatars++;
290			(*iter)->getMotionController().incMotionCounts(num_motions, num_loading_motions, num_loaded_motions, num_active_motions, num_deprecated_motions);
291		}
292		
293		x = xleft;
294		tdesc = llformat("Total Bytes: %d MB Overhead: %d KB Avs %d Motions:%d Loading:%d Loaded:%d Active:%d Dep:%d",
295						 LLMemType::sTotalMem >> 20, LLMemType::sOverheadMem >> 10,
296						 num_avatars, num_motions, num_loading_motions, num_loaded_motions, num_active_motions, num_deprecated_motions);
297		LLFontGL::getFontMonospace()->renderUTF8(tdesc, 0, x, y, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP);
298	}
299
300	// Bars
301	y = ytop;
302	labelwidth += 8;
303	S32 barw = width - labelwidth - xleft - margin;
304	for (S32 i=0; i<MTV_DISPLAY_NUM; i++)
305	{
306		x = xleft + labelwidth;
307
308		int tidx = mtv_display_table[i].memtype;
309		S32 bytes = LLMemType::sMemCount[tidx];
310		F32 frac = (F32)bytes / (F32)maxmaxbytes;
311		S32 w = (S32)(frac * (F32)barw);
312		left = x; right = x + w;
313		top = y; bottom = y - texth;		
314		gl_rect_2d(left, top, right, bottom, *mtv_display_table[i].color);
315
316		S32 maxbytes = LLMemType::sMaxMemCount[tidx];
317		F32 frac2 = (F32)maxbytes / (F32)maxmaxbytes;
318		S32 w2 = (S32)(frac2 * (F32)barw);
319		left = x + w + 1; right = x + w2;
320		top = y; bottom = y - texth;
321		LLColor4 tcolor = *mtv_display_table[i].color;
322		tcolor.setAlpha(.5f);
323		gl_rect_2d(left, top, right, bottom, tcolor);
324		
325		y -= (texth + 2);
326	}
327
328	dumpData();
329
330#endif
331	
332	LLView::draw();
333}