PageRenderTime 102ms CodeModel.GetById 42ms app.highlight 52ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/newview/llviewerstats.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 862 lines | 617 code | 111 blank | 134 comment | 48 complexity | 655cc05ae929b1457dd8ccc9de6682f6 MD5 | raw file
  1/** 
  2 * @file llviewerstats.cpp
  3 * @brief LLViewerStats class implementation
  4 *
  5 * $LicenseInfo:firstyear=2002&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 "llviewerstats.h"
 30#include "llviewerthrottle.h"
 31
 32#include "message.h"
 33#include "llfloaterreg.h"
 34#include "llmemory.h"
 35#include "lltimer.h"
 36#include "llvfile.h"
 37
 38#include "llappviewer.h"
 39
 40#include "pipeline.h" 
 41#include "lltexturefetch.h" 
 42#include "llviewerobjectlist.h" 
 43#include "llviewertexturelist.h" 
 44#include "lltexlayer.h"
 45#include "lltexlayerparams.h"
 46#include "llsurface.h"
 47#include "llvlmanager.h"
 48#include "llagent.h"
 49#include "llagentcamera.h"
 50#include "llviewercontrol.h"
 51#include "llversioninfo.h"
 52#include "llfloatertools.h"
 53#include "lldebugview.h"
 54#include "llfasttimerview.h"
 55#include "llviewerregion.h"
 56#include "llvoavatar.h"
 57#include "llvoavatarself.h"
 58#include "llviewerwindow.h"		// *TODO: remove, only used for width/height
 59#include "llworld.h"
 60#include "llfeaturemanager.h"
 61#include "llviewernetwork.h"
 62#include "llmeshrepository.h" //for LLMeshRepository::sBytesReceived
 63
 64
 65class StatAttributes
 66{
 67public:
 68	StatAttributes(const char* name,
 69				   const BOOL enabled,
 70				   const BOOL is_timer)
 71		: mName(name),
 72		  mEnabled(enabled),
 73		  mIsTimer(is_timer)
 74	{
 75	}
 76	
 77	std::string mName;
 78	BOOL mEnabled;
 79	BOOL mIsTimer;
 80};
 81
 82const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] =
 83{
 84	// ST_VERSION
 85	StatAttributes("Version", TRUE, FALSE),
 86	// ST_AVATAR_EDIT_SECONDS
 87	StatAttributes("Seconds in Edit Appearence", FALSE, TRUE),
 88	// ST_TOOLBOX_SECONDS
 89	StatAttributes("Seconds using Toolbox", FALSE, TRUE),
 90	// ST_CHAT_COUNT
 91	StatAttributes("Chat messages sent", FALSE, FALSE),
 92	// ST_IM_COUNT
 93	StatAttributes("IMs sent", FALSE, FALSE),
 94	// ST_FULLSCREEN_BOOL
 95	StatAttributes("Fullscreen mode", FALSE, FALSE),
 96	// ST_RELEASE_COUNT
 97	StatAttributes("Object release count", FALSE, FALSE),
 98	// ST_CREATE_COUNT
 99	StatAttributes("Object create count", FALSE, FALSE),
100	// ST_REZ_COUNT
101	StatAttributes("Object rez count", FALSE, FALSE),
102	// ST_FPS_10_SECONDS
103	StatAttributes("Seconds below 10 FPS", FALSE, TRUE),
104	// ST_FPS_2_SECONDS
105	StatAttributes("Seconds below 2 FPS", FALSE, TRUE),
106	// ST_MOUSELOOK_SECONDS
107	StatAttributes("Seconds in Mouselook", FALSE, TRUE),
108	// ST_FLY_COUNT
109	StatAttributes("Fly count", FALSE, FALSE),
110	// ST_TELEPORT_COUNT
111	StatAttributes("Teleport count", FALSE, FALSE),
112	// ST_OBJECT_DELETE_COUNT
113	StatAttributes("Objects deleted", FALSE, FALSE),
114	// ST_SNAPSHOT_COUNT
115	StatAttributes("Snapshots taken", FALSE, FALSE),
116	// ST_UPLOAD_SOUND_COUNT
117	StatAttributes("Sounds uploaded", FALSE, FALSE),
118	// ST_UPLOAD_TEXTURE_COUNT
119	StatAttributes("Textures uploaded", FALSE, FALSE),
120	// ST_EDIT_TEXTURE_COUNT
121	StatAttributes("Changes to textures on objects", FALSE, FALSE),
122	// ST_KILLED_COUNT
123	StatAttributes("Number of times killed", FALSE, FALSE),
124	// ST_FRAMETIME_JITTER
125	StatAttributes("Average delta between sucessive frame times", FALSE, FALSE),
126	// ST_FRAMETIME_SLEW
127	StatAttributes("Average delta between frame time and mean", FALSE, FALSE),
128	// ST_INVENTORY_TOO_LONG
129	StatAttributes("Inventory took too long to load", FALSE, FALSE),
130	// ST_WEARABLES_TOO_LONG
131	StatAttributes("Wearables took too long to load", FALSE, FALSE),
132	// ST_LOGIN_SECONDS
133	StatAttributes("Time between LoginRequest and LoginReply", FALSE, FALSE),
134	// ST_LOGIN_TIMEOUT_COUNT
135	StatAttributes("Number of login attempts that timed out", FALSE, FALSE),
136	// ST_HAS_BAD_TIMER
137	StatAttributes("Known bad timer if != 0.0", FALSE, FALSE),
138	// ST_DOWNLOAD_FAILED
139	StatAttributes("Number of times LLAssetStorage::getAssetData() has failed", FALSE, FALSE),
140	// ST_LSL_SAVE_COUNT
141	StatAttributes("Number of times user has saved a script", FALSE, FALSE),
142	// ST_UPLOAD_ANIM_COUNT
143	StatAttributes("Animations uploaded", FALSE, FALSE),
144	// ST_FPS_8_SECONDS
145	StatAttributes("Seconds below 8 FPS", FALSE, TRUE),
146	// ST_SIM_FPS_20_SECONDS
147	StatAttributes("Seconds with sim FPS below 20", FALSE, TRUE),
148	// ST_PHYS_FPS_20_SECONDS
149	StatAttributes("Seconds with physics FPS below 20", FALSE, TRUE),
150	// ST_LOSS_05_SECONDS
151	StatAttributes("Seconds with packet loss > 5%", FALSE, TRUE),
152	// ST_FPS_DROP_50_RATIO
153	StatAttributes("Ratio of frames 2x longer than previous", FALSE, FALSE),
154	// ST_ENABLE_VBO
155	StatAttributes("Vertex Buffers Enabled", TRUE, FALSE),
156	// ST_DELTA_BANDWIDTH
157	StatAttributes("Increase/Decrease in bandwidth based on packet loss", FALSE, FALSE),
158	// ST_MAX_BANDWIDTH
159	StatAttributes("Max bandwidth setting", FALSE, FALSE),
160	// ST_LIGHTING_DETAIL
161	StatAttributes("Lighting Detail", FALSE, FALSE),
162	// ST_VISIBLE_AVATARS
163	StatAttributes("Visible Avatars", FALSE, FALSE),
164	// ST_SHADER_OJECTS
165	StatAttributes("Object Shaders", FALSE, FALSE),
166	// ST_SHADER_ENVIRONMENT
167	StatAttributes("Environment Shaders", FALSE, FALSE),
168	// ST_VISIBLE_DRAW_DIST
169	StatAttributes("Draw Distance", FALSE, FALSE),
170	// ST_VISIBLE_CHAT_BUBBLES
171	StatAttributes("Chat Bubbles Enabled", FALSE, FALSE),
172	// ST_SHADER_AVATAR
173	StatAttributes("Avatar Shaders", FALSE, FALSE),
174	// ST_FRAME_SECS
175	StatAttributes("FRAME_SECS", FALSE, FALSE),
176	// ST_UPDATE_SECS
177	StatAttributes("UPDATE_SECS", FALSE, FALSE),
178	// ST_NETWORK_SECS
179	StatAttributes("NETWORK_SECS", FALSE, FALSE),
180	// ST_IMAGE_SECS
181	StatAttributes("IMAGE_SECS", FALSE, FALSE),
182	// ST_REBUILD_SECS
183	StatAttributes("REBUILD_SECS", FALSE, FALSE),
184	// ST_RENDER_SECS
185	StatAttributes("RENDER_SECS", FALSE, FALSE),
186	// ST_CROSSING_AVG
187	StatAttributes("CROSSING_AVG", FALSE, FALSE),
188	// ST_CROSSING_MAX
189	StatAttributes("CROSSING_MAX", FALSE, FALSE),
190	// ST_LIBXUL_WIDGET_USED
191	StatAttributes("LibXUL Widget used", FALSE, FALSE), // Unused
192	// ST_WINDOW_WIDTH
193	StatAttributes("Window width", FALSE, FALSE),
194	// ST_WINDOW_HEIGHT
195	StatAttributes("Window height", FALSE, FALSE),
196	// ST_TEX_BAKES
197	StatAttributes("Texture Bakes", FALSE, FALSE),
198	// ST_TEX_REBAKES
199	StatAttributes("Texture Rebakes", FALSE, FALSE)
200
201};
202
203LLViewerStats::LLViewerStats() :
204	mKBitStat("kbitstat"),
205	mLayersKBitStat("layerskbitstat"),
206	mObjectKBitStat("objectkbitstat"),
207	mAssetKBitStat("assetkbitstat"),
208	mTextureKBitStat("texturekbitstat"),
209	mVFSPendingOperations("vfspendingoperations"),
210	mObjectsDrawnStat("objectsdrawnstat"),
211	mObjectsCulledStat("objectsculledstat"),
212	mObjectsTestedStat("objectstestedstat"),
213	mObjectsComparedStat("objectscomparedstat"),
214	mObjectsOccludedStat("objectsoccludedstat"),
215	mFPSStat("fpsstat"),
216	mPacketsInStat("packetsinstat"),
217	mPacketsLostStat("packetsloststat"),
218	mPacketsOutStat("packetsoutstat"),
219	mPacketsLostPercentStat("packetslostpercentstat", 64),
220	mTexturePacketsStat("texturepacketsstat"),
221	mActualInKBitStat("actualinkbitstat"),
222	mActualOutKBitStat("actualoutkbitstat"),
223	mTrianglesDrawnStat("trianglesdrawnstat"),
224	mSimTimeDilation("simtimedilation"),
225	mSimFPS("simfps"),
226	mSimPhysicsFPS("simphysicsfps"),
227	mSimAgentUPS("simagentups"),
228	mSimScriptEPS("simscripteps"),
229	mSimFrameMsec("simframemsec"),
230	mSimNetMsec("simnetmsec"),
231	mSimSimOtherMsec("simsimothermsec"),
232	mSimSimPhysicsMsec("simsimphysicsmsec"),
233	mSimSimPhysicsStepMsec("simsimphysicsstepmsec"),
234	mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"),
235	mSimSimPhysicsOtherMsec("simsimphysicsothermsec"),
236	mSimAgentMsec("simagentmsec"),
237	mSimImagesMsec("simimagesmsec"),
238	mSimScriptMsec("simscriptmsec"),
239	mSimSpareMsec("simsparemsec"),
240	mSimSleepMsec("simsleepmsec"),
241	mSimPumpIOMsec("simpumpiomsec"),
242	mSimMainAgents("simmainagents"),
243	mSimChildAgents("simchildagents"),
244	mSimObjects("simobjects"),
245	mSimActiveObjects("simactiveobjects"),
246	mSimActiveScripts("simactivescripts"),
247	mSimInPPS("siminpps"),
248	mSimOutPPS("simoutpps"),
249	mSimPendingDownloads("simpendingdownloads"),
250	mSimPendingUploads("simpendinguploads"),
251	mSimPendingLocalUploads("simpendinglocaluploads"),
252	mSimTotalUnackedBytes("simtotalunackedbytes"),
253	mPhysicsPinnedTasks("physicspinnedtasks"),
254	mPhysicsLODTasks("physicslodtasks"),
255	mPhysicsMemoryAllocated("physicsmemoryallocated"),
256	mSimPingStat("simpingstat"),
257	mNumImagesStat("numimagesstat", 32, TRUE),
258	mNumRawImagesStat("numrawimagesstat", 32, TRUE),
259	mGLTexMemStat("gltexmemstat", 32, TRUE),
260	mGLBoundMemStat("glboundmemstat", 32, TRUE),
261	mRawMemStat("rawmemstat", 32, TRUE),
262	mFormattedMemStat("formattedmemstat", 32, TRUE),
263	mNumObjectsStat("numobjectsstat"),
264	mNumActiveObjectsStat("numactiveobjectsstat"),
265	mNumNewObjectsStat("numnewobjectsstat"),
266	mNumSizeCulledStat("numsizeculledstat"),
267	mNumVisCulledStat("numvisculledstat"),
268	mLastTimeDiff(0.0)
269{
270	for (S32 i = 0; i < ST_COUNT; i++)
271	{
272		mStats[i] = 0.0;
273	}
274	
275	if (LLTimer::knownBadTimer())
276	{
277		mStats[ST_HAS_BAD_TIMER] = 1.0;
278	}	
279	
280	mAgentPositionSnaps.reset();
281}
282
283LLViewerStats::~LLViewerStats()
284{
285}
286
287void LLViewerStats::resetStats()
288{
289	LLViewerStats::getInstance()->mKBitStat.reset();
290	LLViewerStats::getInstance()->mLayersKBitStat.reset();
291	LLViewerStats::getInstance()->mObjectKBitStat.reset();
292	LLViewerStats::getInstance()->mTextureKBitStat.reset();
293	LLViewerStats::getInstance()->mVFSPendingOperations.reset();
294	LLViewerStats::getInstance()->mAssetKBitStat.reset();
295	LLViewerStats::getInstance()->mPacketsInStat.reset();
296	LLViewerStats::getInstance()->mPacketsLostStat.reset();
297	LLViewerStats::getInstance()->mPacketsOutStat.reset();
298	LLViewerStats::getInstance()->mFPSStat.reset();
299	LLViewerStats::getInstance()->mTexturePacketsStat.reset();
300	
301	LLViewerStats::getInstance()->mAgentPositionSnaps.reset();
302}
303
304
305F64 LLViewerStats::getStat(EStatType type) const
306{
307	return mStats[type];
308}
309
310F64 LLViewerStats::setStat(EStatType type, F64 value)
311{
312	mStats[type] = value;
313	return mStats[type];
314}
315
316F64 LLViewerStats::incStat(EStatType type, F64 value)
317{
318	mStats[type] += value;
319	return mStats[type];
320}
321
322void LLViewerStats::updateFrameStats(const F64 time_diff)
323{
324	if (mPacketsLostPercentStat.getCurrent() > 5.0)
325	{
326		incStat(LLViewerStats::ST_LOSS_05_SECONDS, time_diff);
327	}
328	
329	if (mSimFPS.getCurrent() < 20.f && mSimFPS.getCurrent() > 0.f)
330	{
331		incStat(LLViewerStats::ST_SIM_FPS_20_SECONDS, time_diff);
332	}
333	
334	if (mSimPhysicsFPS.getCurrent() < 20.f && mSimPhysicsFPS.getCurrent() > 0.f)
335	{
336		incStat(LLViewerStats::ST_PHYS_FPS_20_SECONDS, time_diff);
337	}
338		
339	if (time_diff >= 0.5)
340	{
341		incStat(LLViewerStats::ST_FPS_2_SECONDS, time_diff);
342	}
343	if (time_diff >= 0.125)
344	{
345		incStat(LLViewerStats::ST_FPS_8_SECONDS, time_diff);
346	}
347	if (time_diff >= 0.1)
348	{
349		incStat(LLViewerStats::ST_FPS_10_SECONDS, time_diff);
350	}
351
352	if (gFrameCount && mLastTimeDiff > 0.0)
353	{
354		// new "stutter" meter
355		setStat(LLViewerStats::ST_FPS_DROP_50_RATIO,
356				(getStat(LLViewerStats::ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + 
357				 (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount);
358			
359
360		// old stats that were never really used
361		setStat(LLViewerStats::ST_FRAMETIME_JITTER,
362				(getStat(LLViewerStats::ST_FRAMETIME_JITTER) * (gFrameCount - 1) + 
363				 fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount);
364			
365		F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount;
366		setStat(LLViewerStats::ST_FRAMETIME_SLEW,
367				(getStat(LLViewerStats::ST_FRAMETIME_SLEW) * (gFrameCount - 1) + 
368				 fabs(average_frametime - time_diff) / average_frametime) / gFrameCount);
369
370		F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
371		F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth;
372		setStat(LLViewerStats::ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f);
373
374		setStat(LLViewerStats::ST_MAX_BANDWIDTH, max_bandwidth / 1024.f);
375		
376	}
377	
378	mLastTimeDiff = time_diff;
379
380}
381
382void LLViewerStats::addToMessage(LLSD &body) const
383{
384	LLSD &misc = body["misc"];
385	
386	for (S32 i = 0; i < ST_COUNT; i++)
387	{
388		if (STAT_INFO[i].mEnabled)
389		{
390			// TODO: send timer value so dataserver can normalize
391			misc[STAT_INFO[i].mName] = mStats[i];
392			llinfos << "STAT: " << STAT_INFO[i].mName << ": " << mStats[i]
393					<< llendl;
394		}
395	}
396	
397	body["AgentPositionSnaps"] = mAgentPositionSnaps.getData();
398	llinfos << "STAT: AgentPositionSnaps: Mean = " << mAgentPositionSnaps.getMean() << "; StdDev = " << mAgentPositionSnaps.getStdDev() 
399			<< "; Count = " << mAgentPositionSnaps.getCount() << llendl;
400}
401
402// static
403// const std::string LLViewerStats::statTypeToText(EStatType type)
404// {
405// 	if (type >= 0 && type < ST_COUNT)
406// 	{
407// 		return STAT_INFO[type].mName;
408// 	}
409// 	else
410// 	{
411// 		return "Unknown statistic";
412// 	}
413// }
414
415// *NOTE:Mani The following methods used to exist in viewer.cpp
416// Moving them here, but not merging them into LLViewerStats yet.
417void reset_statistics()
418{
419	if (LLSurface::sTextureUpdateTime)
420	{
421		LLSurface::sTexelsUpdated = 0;
422		LLSurface::sTextureUpdateTime = 0.f;
423	}
424}
425
426
427void output_statistics(void*)
428{
429	llinfos << "Number of orphans: " << gObjectList.getOrphanCount() << llendl;
430	llinfos << "Number of dead objects: " << gObjectList.mNumDeadObjects << llendl;
431	llinfos << "Num images: " << gTextureList.getNumImages() << llendl;
432	llinfos << "Texture usage: " << LLImageGL::sGlobalTextureMemoryInBytes << llendl;
433	llinfos << "Texture working set: " << LLImageGL::sBoundTextureMemoryInBytes << llendl;
434	llinfos << "Raw usage: " << LLImageRaw::sGlobalRawMemory << llendl;
435	llinfos << "Formatted usage: " << LLImageFormatted::sGlobalFormattedMemory << llendl;
436	llinfos << "Zombie Viewer Objects: " << LLViewerObject::getNumZombieObjects() << llendl;
437	llinfos << "Number of lights: " << gPipeline.getLightCount() << llendl;
438
439	llinfos << "Memory Usage:" << llendl;
440	llinfos << "--------------------------------" << llendl;
441	llinfos << "Pipeline:" << llendl;
442	llinfos << llendl;
443
444#if LL_SMARTHEAP
445	llinfos << "--------------------------------" << llendl;
446	{
447		llinfos << "sizeof(LLVOVolume) = " << sizeof(LLVOVolume) << llendl;
448
449		U32 total_pool_size = 0;
450		U32 total_used_size = 0;
451		MEM_POOL_INFO pool_info;
452		MEM_POOL_STATUS pool_status;
453		U32 pool_num = 0;
454		for(pool_status = MemPoolFirst( &pool_info, 1 ); 
455			pool_status != MEM_POOL_END; 
456			pool_status = MemPoolNext( &pool_info, 1 ) )
457		{
458			llinfos << "Pool #" << pool_num << llendl;
459			if( MEM_POOL_OK != pool_status )
460			{
461				llwarns << "Pool not ok" << llendl;
462				continue;
463			}
464
465			llinfos << "Pool blockSizeFS " << pool_info.blockSizeFS
466				<< " pageSize " << pool_info.pageSize
467				<< llendl;
468
469			U32 pool_count = MemPoolCount(pool_info.pool);
470			llinfos << "Blocks " << pool_count << llendl;
471
472			U32 pool_size = MemPoolSize( pool_info.pool );
473			if( pool_size == MEM_ERROR_RET )
474			{
475				llinfos << "MemPoolSize() failed (" << pool_num << ")" << llendl;
476			}
477			else
478			{
479				llinfos << "MemPool Size " << pool_size / 1024 << "K" << llendl;
480			}
481
482			total_pool_size += pool_size;
483
484			if( !MemPoolLock( pool_info.pool ) )
485			{
486				llinfos << "MemPoolLock failed (" << pool_num << ") " << llendl;
487				continue;
488			}
489
490			U32 used_size = 0; 
491			MEM_POOL_ENTRY entry;
492			entry.entry = NULL;
493			while( MemPoolWalk( pool_info.pool, &entry ) == MEM_POOL_OK )
494			{
495				if( entry.isInUse )
496				{
497					used_size += entry.size;
498				}
499			}
500
501			MemPoolUnlock( pool_info.pool );
502
503			llinfos << "MemPool Used " << used_size/1024 << "K" << llendl;
504			total_used_size += used_size;
505			pool_num++;
506		}
507		
508		llinfos << "Total Pool Size " << total_pool_size/1024 << "K" << llendl;
509		llinfos << "Total Used Size " << total_used_size/1024 << "K" << llendl;
510
511	}
512#endif
513
514	llinfos << "--------------------------------" << llendl;
515	llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl;
516	LLTexLayerStaticImageList::getInstance()->dumpByteCount();
517	LLVOAvatarSelf::dumpScratchTextureByteCount();
518	LLTexLayerSetBuffer::dumpTotalByteCount();
519	LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
520	LLTexLayerParamAlpha::dumpCacheByteCount();
521	LLVOAvatar::dumpBakedStatus();
522
523	llinfos << llendl;
524
525	llinfos << "Object counts:" << llendl;
526	S32 i;
527	S32 obj_counts[256];
528//	S32 app_angles[256];
529	for (i = 0; i < 256; i++)
530	{
531		obj_counts[i] = 0;
532	}
533	for (i = 0; i < gObjectList.getNumObjects(); i++)
534	{
535		LLViewerObject *objectp = gObjectList.getObject(i);
536		if (objectp)
537		{
538			obj_counts[objectp->getPCode()]++;
539		}
540	}
541	for (i = 0; i < 256; i++)
542	{
543		if (obj_counts[i])
544		{
545			llinfos << LLPrimitive::pCodeToString(i) << ":" << obj_counts[i] << llendl;
546		}
547	}
548}
549
550
551U32		gTotalLandIn = 0, gTotalLandOut = 0;
552U32		gTotalWaterIn = 0, gTotalWaterOut = 0;
553
554F32		gAveLandCompression = 0.f, gAveWaterCompression = 0.f;
555F32		gBestLandCompression = 1.f, gBestWaterCompression = 1.f;
556F32		gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f;
557
558
559
560U32		gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
561U32		gObjectBits = 0;
562F32		gAvgSimPing = 0.f;
563U32     gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0};
564
565extern U32  gVisCompared;
566extern U32  gVisTested;
567
568std::map<S32,LLFrameTimer> gDebugTimers;
569std::map<S32,std::string> gDebugTimerLabel;
570
571void init_statistics()
572{
573	// Label debug timers
574	gDebugTimerLabel[0] = "Texture";
575}
576
577void update_statistics(U32 frame_count)
578{
579	gTotalWorldBytes += gVLManager.getTotalBytes();
580	gTotalObjectBytes += gObjectBits / 8;
581
582	// make sure we have a valid time delta for this frame
583	if (gFrameIntervalSeconds > 0.f)
584	{
585		if (gAgentCamera.getCameraMode() == CAMERA_MODE_MOUSELOOK)
586		{
587			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds);
588		}
589		else if (gAgentCamera.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
590		{
591			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds);
592		}
593		else if (LLFloaterReg::instanceVisible("build"))
594		{
595			LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
596		}
597	}
598	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable"));
599	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail());
600	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip"));
601	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles"));
602#if 0 // 1.9.2
603	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject"));
604	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar"));
605	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment"));
606#endif
607	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame"));
608	F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle");
609	F64 network_secs = gDebugView->mFastTimerView->getTime("Network");
610	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs);
611	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs);
612	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images"));
613	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State"));
614	LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry"));
615		
616	LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
617	if (cdp)
618	{
619		LLViewerStats::getInstance()->mSimPingStat.addValue(cdp->getPingDelay());
620		gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1);
621		gSimPingCount++;
622	}
623	else
624	{
625		LLViewerStats::getInstance()->mSimPingStat.addValue(10000);
626	}
627
628	LLViewerStats::getInstance()->mFPSStat.addValue(1);
629	F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
630	LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f);
631	LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f);
632	LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
633	LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
634	gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
635
636	if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
637	{
638		gDebugTimers[0].pause();
639	}
640	else
641	{
642		gDebugTimers[0].unpause();
643	}
644	
645	{
646		static F32 visible_avatar_frames = 0.f;
647		static F32 avg_visible_avatars = 0;
648		F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars;
649		if (visible_avatars > 0.f)
650		{
651			visible_avatar_frames = 1.f;
652			avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames;
653		}
654		LLViewerStats::getInstance()->setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars);
655	}
656	LLWorld::getInstance()->updateNetStats();
657	LLWorld::getInstance()->requestCacheMisses();
658	
659	// Reset all of these values.
660	gVLManager.resetBitCounts();
661	gObjectBits = 0;
662//	gDecodedBits = 0;
663
664	// Only update texture stats periodically so that they are less noisy
665	{
666		static const F32 texture_stats_freq = 10.f;
667		static LLFrameTimer texture_stats_timer;
668		if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
669		{
670			LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
671			LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
672			gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
673			LLViewerTextureList::sTextureBits = 0;
674			LLViewerTextureList::sTexturePackets = 0;
675			texture_stats_timer.reset();
676		}
677	}
678
679}
680
681class ViewerStatsResponder : public LLHTTPClient::Responder
682{
683public:
684    ViewerStatsResponder() { }
685
686    void error(U32 statusNum, const std::string& reason)
687    {
688		llinfos << "ViewerStatsResponder::error " << statusNum << " "
689				<< reason << llendl;
690    }
691
692    void result(const LLSD& content)
693    {
694		llinfos << "ViewerStatsResponder::result" << llendl;
695	}
696};
697
698/*
699 * The sim-side LLSD is in newsim/llagentinfo.cpp:forwardViewerStats.
700 *
701 * There's also a compatibility shim for the old fixed-format sim
702 * stats in newsim/llagentinfo.cpp:processViewerStats.
703 *
704 * If you move stats around here, make the corresponding changes in
705 * those locations, too.
706 */
707void send_stats()
708{
709	// IW 9/23/02 I elected not to move this into LLViewerStats
710	// because it depends on too many viewer.cpp globals.
711	// Someday we may want to merge all our stats into a central place
712	// but that day is not today.
713
714	// Only send stats if the agent is connected to a region.
715	if (!gAgent.getRegion())
716	{
717		return;
718	}
719
720	LLSD body;
721	std::string url = gAgent.getRegion()->getCapability("ViewerStats");
722
723	if (url.empty()) {
724		llwarns << "Could not get ViewerStats capability" << llendl;
725		return;
726	}
727	
728	body["session_id"] = gAgentSessionID;
729	
730	LLSD &agent = body["agent"];
731	
732	time_t ltime;
733	time(&ltime);
734	F32 run_time = F32(LLFrameTimer::getElapsedSeconds());
735
736	agent["start_time"] = S32(ltime - S32(run_time));
737
738	// The first stat set must have a 0 run time if it doesn't actually
739	// contain useful data in terms of FPS, etc.  We use half the
740	// SEND_STATS_PERIOD seconds as the point at which these statistics become
741	// valid.  Data warehouse uses a 0 value here to easily discard these
742	// records with non-useful FPS values etc.
743	if (run_time < (SEND_STATS_PERIOD / 2))
744	{
745		agent["run_time"] = 0.0f;
746	}
747	else
748	{
749		agent["run_time"] = run_time;
750	}
751
752	// send fps only for time app spends in foreground
753	agent["fps"] = (F32)gForegroundFrameCount / gForegroundTime.getElapsedTimeF32();
754	agent["version"] = LLVersionInfo::getChannelAndVersion();
755	std::string language = LLUI::getLanguage();
756	agent["language"] = language;
757	
758	agent["sim_fps"] = ((F32) gFrameCount - gSimFrames) /
759		(F32) (gRenderStartTime.getElapsedTimeF32() - gSimLastTime);
760
761	gSimLastTime = gRenderStartTime.getElapsedTimeF32();
762	gSimFrames   = (F32) gFrameCount;
763
764	agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
765	agent["ping"] = gAvgSimPing;
766	agent["meters_traveled"] = gAgent.getDistanceTraveled();
767	agent["regions_visited"] = gAgent.getRegionsVisited();
768	agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
769
770	LLSD &system = body["system"];
771	
772	system["ram"] = (S32) gSysMemory.getPhysicalMemoryKB();
773	system["os"] = LLAppViewer::instance()->getOSInfo().getOSStringSimple();
774	system["cpu"] = gSysCPU.getCPUString();
775	unsigned char MACAddress[MAC_ADDRESS_BYTES];
776	LLUUID::getNodeID(MACAddress);
777	std::string macAddressString = llformat("%02x-%02x-%02x-%02x-%02x-%02x",
778											MACAddress[0],MACAddress[1],MACAddress[2],
779											MACAddress[3],MACAddress[4],MACAddress[5]);
780	system["mac_address"] = macAddressString;
781	system["serial_number"] = LLAppViewer::instance()->getSerialNumber();
782	std::string gpu_desc = llformat(
783		"%-6s Class %d ",
784		gGLManager.mGLVendorShort.substr(0,6).c_str(),
785		(S32)LLFeatureManager::getInstance()->getGPUClass())
786		+ LLFeatureManager::getInstance()->getGPUString();
787
788	system["gpu"] = gpu_desc;
789	system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass();
790	system["gpu_vendor"] = gGLManager.mGLVendorShort;
791	system["gpu_version"] = gGLManager.mDriverVersionVendorString;
792
793	LLSD &download = body["downloads"];
794
795	download["world_kbytes"] = gTotalWorldBytes / 1024.0;
796	download["object_kbytes"] = gTotalObjectBytes / 1024.0;
797	download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
798	download["mesh_kbytes"] = LLMeshRepository::sBytesReceived/1024.0;
799
800	LLSD &in = body["stats"]["net"]["in"];
801
802	in["kbytes"] = gMessageSystem->mTotalBytesIn / 1024.0;
803	in["packets"] = (S32) gMessageSystem->mPacketsIn;
804	in["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsIn;
805	in["savings"] = (gMessageSystem->mUncompressedBytesIn -
806					 gMessageSystem->mCompressedBytesIn) / 1024.0;
807	
808	LLSD &out = body["stats"]["net"]["out"];
809	
810	out["kbytes"] = gMessageSystem->mTotalBytesOut / 1024.0;
811	out["packets"] = (S32) gMessageSystem->mPacketsOut;
812	out["compressed_packets"] = (S32) gMessageSystem->mCompressedPacketsOut;
813	out["savings"] = (gMessageSystem->mUncompressedBytesOut -
814					  gMessageSystem->mCompressedBytesOut) / 1024.0;
815
816	LLSD &fail = body["stats"]["failures"];
817
818	fail["send_packet"] = (S32) gMessageSystem->mSendPacketFailureCount;
819	fail["dropped"] = (S32) gMessageSystem->mDroppedPackets;
820	fail["resent"] = (S32) gMessageSystem->mResentPackets;
821	fail["failed_resends"] = (S32) gMessageSystem->mFailedResendPackets;
822	fail["off_circuit"] = (S32) gMessageSystem->mOffCircuitPackets;
823	fail["invalid"] = (S32) gMessageSystem->mInvalidOnCircuitPackets;
824
825	// Misc stats, two strings and two ints
826	// These are not expecticed to persist across multiple releases
827	// Comment any changes with your name and the expected release revision
828	// If the current revision is recent, ping the previous author before overriding
829	LLSD &misc = body["stats"]["misc"];
830
831	// Screen size so the UI team can figure out how big the widgets
832	// appear and use a "typical" size for end user tests.
833
834	S32 window_width = gViewerWindow->getWindowWidthRaw();
835	S32 window_height = gViewerWindow->getWindowHeightRaw();
836	S32 window_size = (window_width * window_height) / 1024;
837	misc["string_1"] = llformat("%d", window_size);
838	if (gDebugTimers.find(0) != gDebugTimers.end() && gFrameTimeSeconds > 0)
839	{
840		misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f", gDebugTimers[0].getElapsedTimeF32(), gFrameTimeSeconds);
841	}
842
843// 	misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21
844// 	misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21
845
846	F32 unbaked_time = LLVOAvatar::sUnbakedTime * 1000.f / gFrameTimeSeconds;
847	misc["int_1"] = LLSD::Integer(unbaked_time); // Steve: 1.22
848	F32 grey_time = LLVOAvatar::sGreyTime * 1000.f / gFrameTimeSeconds;
849	misc["int_2"] = LLSD::Integer(grey_time); // Steve: 1.22
850
851	llinfos << "Misc Stats: int_1: " << misc["int_1"] << " int_2: " << misc["int_2"] << llendl;
852	llinfos << "Misc Stats: string_1: " << misc["string_1"] << " string_2: " << misc["string_2"] << llendl;
853
854	body["DisplayNamesEnabled"] = gSavedSettings.getBOOL("UseDisplayNames");
855	body["DisplayNamesShowUsername"] = gSavedSettings.getBOOL("NameTagShowUsernames");
856	
857	body["MinimalSkin"] = false;
858	
859	LLViewerStats::getInstance()->addToMessage(body);
860	LLHTTPClient::post(url, body, new ViewerStatsResponder());
861}
862