llviewerstats.cpp 35 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190
  1. /**
  2. * @file llviewerstats.cpp
  3. * @brief LLViewerStats class implementation
  4. *
  5. * $LicenseInfo:firstyear=2002&license=viewergpl$
  6. *
  7. * Copyright (c) 2002-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #if LL_LINUX
  34. # include <stdlib.h> // For getenv()
  35. #endif
  36. #include "llviewerstats.h"
  37. #include "llavatarnamecache.h"
  38. #include "llcorehttputil.h"
  39. #include "llfasttimer.h"
  40. #include "llgl.h"
  41. #include "llsdutil.h"
  42. #include "llsys.h"
  43. #include "llmessage.h"
  44. #include "llagent.h"
  45. #include "llappviewer.h"
  46. #include "lldebugview.h"
  47. #include "llfasttimerview.h"
  48. #include "llfeaturemanager.h"
  49. #include "llflexibleobject.h"
  50. #include "llfloatertools.h"
  51. #include "llgridmanager.h"
  52. #include "llmeshrepository.h"
  53. #include "llpipeline.h"
  54. #include "llsurface.h"
  55. #include "lltexturefetch.h"
  56. #include "llviewercontrol.h"
  57. #include "llviewerobjectlist.h"
  58. #include "llviewerregion.h"
  59. #include "llviewertexlayer.h"
  60. #include "llviewertextureanim.h"
  61. #include "llviewertexturelist.h"
  62. #include "llviewerthrottle.h"
  63. #include "llviewerwindow.h"
  64. #include "llvlmanager.h"
  65. #include "llvoavatarself.h"
  66. #include "llworld.h"
  67. constexpr F32 SEND_STATS_PERIOD = 300.f;
  68. constexpr F32 SEND_AVATAR_STATS_PERIOD = 60.f;
  69. static const std::string KEY_AGENTS = "agents"; // map
  70. static const std::string KEY_WEIGHT = "weight"; // integer
  71. static const std::string KEY_TOO_COMPLEX = "tooComplex"; // boolean
  72. static const std::string KEY_OVER_COMPLEXITY_LIMIT = "overlimit"; // integer
  73. static const std::string KEY_REPORTING_COMPLEXITY_LIMIT = "reportinglimit"; // integer
  74. static const std::string KEY_IDENTIFIER = "identifier";
  75. static const std::string KEY_MESSAGE = "message";
  76. static const std::string KEY_ERROR = "error";
  77. // Globals
  78. LLViewerStats gViewerStats;
  79. U32 gTotalLandIn = 0;
  80. U32 gTotalLandOut = 0;
  81. U32 gTotalWaterIn = 0;
  82. U32 gTotalWaterOut = 0;
  83. F32 gAveLandCompression = 0.f;
  84. F32 gAveWaterCompression = 0.f;
  85. F32 gBestLandCompression = 1.f;
  86. F32 gBestWaterCompression = 1.f;
  87. F32 gWorstLandCompression = 0.f;
  88. F32 gWorstWaterCompression = 0.f;
  89. U32 gTotalWorldBytes = 0;
  90. U32 gTotalObjectBytes = 0;
  91. U32 gTotalTextureBytes = 0;
  92. U32 gSimPingCount = 0;
  93. U32 gObjectBits = 0;
  94. F32 gAvgSimPing = 0.f;
  95. extern U32 gVisCompared;
  96. extern U32 gVisTested;
  97. LLFrameTimer gTextureTimer;
  98. class StatAttributes
  99. {
  100. public:
  101. StatAttributes(const char* name, bool enabled, bool is_timer)
  102. : mName(name),
  103. mEnabled(enabled),
  104. mIsTimer(is_timer)
  105. {
  106. }
  107. std::string mName;
  108. bool mEnabled;
  109. bool mIsTimer;
  110. };
  111. const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] =
  112. {
  113. // ST_VERSION
  114. StatAttributes("Version", true, false),
  115. // ST_AVATAR_EDIT_SECONDS
  116. StatAttributes("Seconds in Edit Appearence", false, true),
  117. // ST_TOOLBOX_SECONDS
  118. StatAttributes("Seconds using Toolbox", false, true),
  119. // ST_CHAT_COUNT
  120. StatAttributes("Chat messages sent", false, false),
  121. // ST_IM_COUNT
  122. StatAttributes("IMs sent", false, false),
  123. // ST_FULLSCREEN_BOOL
  124. StatAttributes("Fullscreen mode", false, false),
  125. // ST_RELEASE_COUNT
  126. StatAttributes("Object release count", false, false),
  127. // ST_CREATE_COUNT
  128. StatAttributes("Object create count", false, false),
  129. // ST_REZ_COUNT
  130. StatAttributes("Object rez count", false, false),
  131. // ST_FPS_10_SECONDS
  132. StatAttributes("Seconds below 10 FPS", false, true),
  133. // ST_FPS_2_SECONDS
  134. StatAttributes("Seconds below 2 FPS", false, true),
  135. // ST_MOUSELOOK_SECONDS
  136. StatAttributes("Seconds in Mouselook", false, true),
  137. // ST_FLY_COUNT
  138. StatAttributes("Fly count", false, false),
  139. // ST_TELEPORT_COUNT
  140. StatAttributes("Teleport count", false, false),
  141. // ST_OBJECT_DELETE_COUNT
  142. StatAttributes("Objects deleted", false, false),
  143. // ST_SNAPSHOT_COUNT
  144. StatAttributes("Snapshots taken", false, false),
  145. // ST_UPLOAD_SOUND_COUNT
  146. StatAttributes("Sounds uploaded", false, false),
  147. // ST_UPLOAD_TEXTURE_COUNT
  148. StatAttributes("Textures uploaded", false, false),
  149. // ST_EDIT_TEXTURE_COUNT
  150. StatAttributes("Changes to textures on objects", false, false),
  151. // ST_KILLED_COUNT
  152. StatAttributes("Number of times killed", false, false),
  153. // ST_FRAMETIME_JITTER
  154. StatAttributes("Average delta between sucessive frame times", false,
  155. false),
  156. // ST_FRAMETIME_SLEW
  157. StatAttributes("Average delta between frame time and mean", false, false),
  158. // ST_INVENTORY_TOO_LONG
  159. StatAttributes("Inventory took too long to load", false, false),
  160. // ST_WEARABLES_TOO_LONG
  161. StatAttributes("Wearables took too long to load", false, false),
  162. // ST_LOGIN_SECONDS
  163. StatAttributes("Time between LoginRequest and LoginReply", false, false),
  164. // ST_LOGIN_TIMEOUT_COUNT
  165. StatAttributes("Number of login attempts that timed out", false, false),
  166. // ST_HAS_BAD_TIMER
  167. StatAttributes("Known bad timer if != 0.0", false, false),
  168. // ST_DOWNLOAD_FAILED
  169. StatAttributes("Number of times LLAssetStorage::getAssetData() has failed",
  170. false, false),
  171. // ST_LSL_SAVE_COUNT
  172. StatAttributes("Number of times user has saved a script", false, false),
  173. // ST_UPLOAD_ANIM_COUNT
  174. StatAttributes("Animations uploaded", false, false),
  175. // ST_FPS_8_SECONDS
  176. StatAttributes("Seconds below 8 FPS", false, true),
  177. // ST_SIM_FPS_20_SECONDS
  178. StatAttributes("Seconds with sim FPS below 20", false, true),
  179. // ST_PHYS_FPS_20_SECONDS
  180. StatAttributes("Seconds with physics FPS below 20", false, true),
  181. // ST_LOSS_05_SECONDS
  182. StatAttributes("Seconds with packet loss > 5%", false, true),
  183. // ST_FPS_DROP_50_RATIO
  184. StatAttributes("Ratio of frames 2x longer than previous", false, false),
  185. // ST_DELTA_BANDWIDTH
  186. StatAttributes("Increase/Decrease in bandwidth based on packet loss",
  187. false, false),
  188. // ST_MAX_BANDWIDTH
  189. StatAttributes("Max bandwidth setting", false, false),
  190. // ST_VISIBLE_AVATARS
  191. StatAttributes("Visible Avatars", false, false),
  192. // ST_SHADER_OJECTS
  193. StatAttributes("Object Shaders", false, false),
  194. // ST_SHADER_ENVIRONMENT
  195. StatAttributes("Environment Shaders", false, false),
  196. // ST_VISIBLE_DRAW_DIST
  197. StatAttributes("Draw Distance", false, false),
  198. // ST_VISIBLE_CHAT_BUBBLES
  199. StatAttributes("Chat Bubbles Enabled", false, false),
  200. // ST_SHADER_AVATAR
  201. StatAttributes("Avatar Shaders", false, false),
  202. // ST_FRAME_SECS
  203. StatAttributes("FRAME_SECS", false, false),
  204. // ST_UPDATE_SECS
  205. StatAttributes("UPDATE_SECS", false, false),
  206. // ST_NETWORK_SECS
  207. StatAttributes("NETWORK_SECS", false, false),
  208. // ST_IMAGE_SECS
  209. StatAttributes("IMAGE_SECS", false, false),
  210. // ST_REBUILD_SECS
  211. StatAttributes("REBUILD_SECS", false, false),
  212. // ST_RENDER_SECS
  213. StatAttributes("RENDER_SECS", false, false),
  214. // ST_CROSSING_AVG
  215. StatAttributes("CROSSING_AVG", false, false),
  216. // ST_CROSSING_MAX
  217. StatAttributes("CROSSING_MAX", false, false),
  218. // ST_WINDOW_WIDTH
  219. StatAttributes("Window width", false, false),
  220. // ST_WINDOW_HEIGHT
  221. StatAttributes("Window height", false, false),
  222. // ST_TEX_BAKES
  223. StatAttributes("Texture Bakes", false, false),
  224. // ST_TEX_REBAKES
  225. StatAttributes("Texture Rebakes", false, false)
  226. };
  227. LLViewerStats::LLViewerStats()
  228. : mPacketsLostPercentStat(64),
  229. mLastTimeDiff(0.0),
  230. // Initialize mNextStatsSendingTime with 0 so that the initial stats report
  231. // will be sent immediately.
  232. mNextStatsSendingTime(0),
  233. mNextAvStatsSendingTime(SEND_AVATAR_STATS_PERIOD),
  234. mComplexityReports(0),
  235. mTooComplexReports(0)
  236. {
  237. for (S32 i = 0; i < ST_COUNT; ++i)
  238. {
  239. mStats[i] = 0.0;
  240. }
  241. }
  242. void LLViewerStats::resetStats()
  243. {
  244. mKBitStat.reset();
  245. mLayersKBitStat.reset();
  246. mObjectKBitStat.reset();
  247. mTextureKBitStat.reset();
  248. mAssetKBitStat.reset();
  249. mPacketsInStat.reset();
  250. mPacketsLostStat.reset();
  251. mPacketsOutStat.reset();
  252. mFPSStat.reset();
  253. mTexturePacketsStat.reset();
  254. mNextStatsSendingTime = 0;
  255. mNextAvStatsSendingTime = gFrameTimeSeconds + SEND_AVATAR_STATS_PERIOD;
  256. }
  257. void LLViewerStats::idleUpdate()
  258. {
  259. if (LLSurface::sTextureUpdateTime)
  260. {
  261. LLSurface::sTexelsUpdatedPerSecStat.addValue(0.001f *
  262. (LLSurface::sTexelsUpdated /
  263. LLSurface::sTextureUpdateTime));
  264. LLSurface::sTexelsUpdated = 0;
  265. LLSurface::sTextureUpdateTime = 0.f;
  266. }
  267. if (gFrameTimeSeconds >= mNextStatsSendingTime)
  268. {
  269. sendStats();
  270. }
  271. if (gFrameTimeSeconds >= mNextAvStatsSendingTime)
  272. {
  273. avatarRenderingStats();
  274. }
  275. }
  276. void LLViewerStats::addSample(U32 stat_id, F32 stat_value)
  277. {
  278. if (llisnan(stat_value))
  279. {
  280. llwarns_once << "NaN value received for stat: " << stat_id << llendl;
  281. return;
  282. }
  283. switch (stat_id)
  284. {
  285. case LL_SIM_STAT_TIME_DILATION:
  286. mSimTimeDilation.addValue(stat_value);
  287. break;
  288. case LL_SIM_STAT_FPS:
  289. mSimFPS.addValue(stat_value);
  290. break;
  291. case LL_SIM_STAT_PHYSFPS:
  292. mSimPhysicsFPS.addValue(stat_value);
  293. break;
  294. case LL_SIM_STAT_AGENTUPS:
  295. mSimAgentUPS.addValue(stat_value);
  296. break;
  297. case LL_SIM_STAT_FRAMEMS:
  298. mSimFrameMsec.addValue(stat_value);
  299. break;
  300. case LL_SIM_STAT_NETMS:
  301. mSimNetMsec.addValue(stat_value);
  302. break;
  303. case LL_SIM_STAT_SIMOTHERMS:
  304. mSimSimOtherMsec.addValue(stat_value);
  305. break;
  306. case LL_SIM_STAT_SIMPHYSICSMS:
  307. mSimSimPhysicsMsec.addValue(stat_value);
  308. break;
  309. case LL_SIM_STAT_AGENTMS:
  310. mSimAgentMsec.addValue(stat_value);
  311. break;
  312. case LL_SIM_STAT_IMAGESMS:
  313. mSimImagesMsec.addValue(stat_value);
  314. break;
  315. case LL_SIM_STAT_SCRIPTMS:
  316. mSimScriptMsec.addValue(stat_value);
  317. break;
  318. case LL_SIM_STAT_NUMTASKS:
  319. mSimObjects.addValue(stat_value);
  320. break;
  321. case LL_SIM_STAT_NUMTASKSACTIVE:
  322. mSimActiveObjects.addValue(stat_value);
  323. break;
  324. case LL_SIM_STAT_NUMAGENTMAIN:
  325. mSimMainAgents.addValue(stat_value);
  326. break;
  327. case LL_SIM_STAT_NUMAGENTCHILD:
  328. mSimChildAgents.addValue(stat_value);
  329. break;
  330. case LL_SIM_STAT_NUMSCRIPTSACTIVE:
  331. mSimActiveScripts.addValue(stat_value);
  332. break;
  333. case LL_SIM_STAT_SCRIPT_EPS:
  334. mSimScriptEPS.addValue(stat_value);
  335. break;
  336. case LL_SIM_STAT_INPPS:
  337. mSimInPPS.addValue(stat_value);
  338. break;
  339. case LL_SIM_STAT_OUTPPS:
  340. mSimOutPPS.addValue(stat_value);
  341. break;
  342. case LL_SIM_STAT_PENDING_DOWNLOADS:
  343. mSimPendingDownloads.addValue(stat_value);
  344. break;
  345. case LL_SIM_STAT_PENDING_UPLOADS:
  346. mSimPendingUploads.addValue(stat_value);
  347. break;
  348. case LL_SIM_STAT_PENDING_LOCAL_UPLOADS:
  349. mSimPendingLocalUploads.addValue(stat_value);
  350. break;
  351. case LL_SIM_STAT_TOTAL_UNACKED_BYTES:
  352. {
  353. constexpr F32 scaler = 1.f / 1024.f;
  354. mSimTotalUnackedBytes.addValue(stat_value * scaler);
  355. break;
  356. }
  357. case LL_SIM_STAT_PHYSICS_PINNED_TASKS:
  358. mPhysicsPinnedTasks.addValue(stat_value);
  359. break;
  360. case LL_SIM_STAT_PHYSICS_LOD_TASKS:
  361. mPhysicsLODTasks.addValue(stat_value);
  362. break;
  363. case LL_SIM_STAT_SIMPHYSICSSTEPMS:
  364. mSimSimPhysicsStepMsec.addValue(stat_value);
  365. break;
  366. case LL_SIM_STAT_SIMPHYSICSSHAPEMS:
  367. mSimSimPhysicsShapeUpdateMsec.addValue(stat_value);
  368. break;
  369. case LL_SIM_STAT_SIMPHYSICSOTHERMS:
  370. mSimSimPhysicsOtherMsec.addValue(stat_value);
  371. break;
  372. case LL_SIM_STAT_SIMPHYSICSMEMORY:
  373. mPhysicsMemoryAllocated.addValue(stat_value);
  374. break;
  375. case LL_SIM_STAT_SIMSPARETIME:
  376. mSimSpareMsec.addValue(stat_value);
  377. break;
  378. case LL_SIM_STAT_SIMSLEEPTIME:
  379. mSimSleepMsec.addValue(stat_value);
  380. break;
  381. case LL_SIM_STAT_IOPUMPTIME:
  382. mSimPumpIOMsec.addValue(stat_value);
  383. break;
  384. case LL_SIM_STAT_PCTSCRIPTSRUN:
  385. mSimPctScriptsRun.addValue(stat_value);
  386. break;
  387. case LL_SIM_STAT_SIMAISTEPTIMEMS:
  388. mSimSimAIStepMsec.addValue(stat_value);
  389. break;
  390. case LL_SIM_STAT_SKIPPEDAISILSTEPS_PS:
  391. mSimSimSkippedSilhouetteSteps.addValue(stat_value);
  392. break;
  393. case LL_SIM_STAT_PCTSTEPPEDCHARACTERS:
  394. mSimSimPctSteppedCharacters.addValue(stat_value);
  395. break;
  396. default:
  397. LL_DEBUGS("Messaging") << "Unknown stat id " << stat_id << LL_ENDL;
  398. }
  399. }
  400. void LLViewerStats::updateFrameStats(F64 time_diff)
  401. {
  402. if (mPacketsLostPercentStat.getCurrent() > 5.0)
  403. {
  404. incStat(ST_LOSS_05_SECONDS, time_diff);
  405. }
  406. if (mSimFPS.getCurrent() < 20.f && mSimFPS.getCurrent() > 0.f)
  407. {
  408. incStat(ST_SIM_FPS_20_SECONDS, time_diff);
  409. }
  410. if (mSimPhysicsFPS.getCurrent() < 20.f &&
  411. mSimPhysicsFPS.getCurrent() > 0.f)
  412. {
  413. incStat(ST_PHYS_FPS_20_SECONDS, time_diff);
  414. }
  415. if (time_diff >= 0.5)
  416. {
  417. incStat(ST_FPS_2_SECONDS, time_diff);
  418. }
  419. if (time_diff >= 0.125)
  420. {
  421. incStat(ST_FPS_8_SECONDS, time_diff);
  422. }
  423. if (time_diff >= 0.1)
  424. {
  425. incStat(ST_FPS_10_SECONDS, time_diff);
  426. }
  427. if (gFrameCount && mLastTimeDiff > 0.0)
  428. {
  429. // New "stutter" meter
  430. setStat(ST_FPS_DROP_50_RATIO,
  431. (getStat(ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) +
  432. (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount);
  433. // Old stats that were never really used
  434. setStat(ST_FRAMETIME_JITTER,
  435. (getStat(ST_FRAMETIME_JITTER) * (gFrameCount - 1) +
  436. fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount);
  437. F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount;
  438. setStat(ST_FRAMETIME_SLEW,
  439. (getStat(ST_FRAMETIME_SLEW) * (gFrameCount - 1) +
  440. fabs(average_frametime - time_diff) / average_frametime) / gFrameCount);
  441. F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
  442. F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth;
  443. setStat(ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f);
  444. setStat(ST_MAX_BANDWIDTH, max_bandwidth / 1024.f);
  445. }
  446. mLastTimeDiff = time_diff;
  447. }
  448. void LLViewerStats::addToMessage(LLSD& body) const
  449. {
  450. LLSD& misc = body["misc"];
  451. for (S32 i = 0; i < ST_COUNT; ++i)
  452. {
  453. if (STAT_INFO[i].mEnabled)
  454. {
  455. // *TODO: send timer value so dataserver can normalize
  456. misc[STAT_INFO[i].mName] = mStats[i];
  457. llinfos << "STAT: " << STAT_INFO[i].mName << ": " << mStats[i]
  458. << llendl;
  459. }
  460. }
  461. }
  462. void LLViewerStats::updateStatistics(U32 frame_count)
  463. {
  464. gTotalWorldBytes += gVLManager.getTotalBytes();
  465. gTotalObjectBytes += gObjectBits / 8;
  466. // Make sure we have a valid time delta for this frame
  467. if (gFrameIntervalSeconds > 0.f)
  468. {
  469. if (gAgent.getCameraMode() == CAMERA_MODE_MOUSELOOK)
  470. {
  471. incStat(ST_MOUSELOOK_SECONDS, gFrameIntervalSeconds);
  472. }
  473. else if (gAgent.getCameraMode() == CAMERA_MODE_CUSTOMIZE_AVATAR)
  474. {
  475. incStat(ST_AVATAR_EDIT_SECONDS, gFrameIntervalSeconds);
  476. }
  477. else if (LLFloaterTools::isVisible())
  478. {
  479. incStat(ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
  480. }
  481. }
  482. static LLCachedControl<F32> render_far_clip(gSavedSettings,
  483. "RenderFarClip");
  484. setStat(ST_DRAW_DIST, (F64)render_far_clip);
  485. static LLCachedControl<bool> use_chat_bubbles(gSavedSettings,
  486. "UseChatBubbles");
  487. setStat(ST_CHAT_BUBBLES, (F64)use_chat_bubbles);
  488. #if LL_FAST_TIMERS_ENABLED
  489. if (gEnableFastTimers && gFastTimerViewp)
  490. {
  491. setStat(ST_FRAME_SECS,
  492. gFastTimerViewp->getTime(LLFastTimer::FTM_FRAME));
  493. F64 idle_secs = gFastTimerViewp->getTime(LLFastTimer::FTM_IDLE);
  494. F64 network_secs = gFastTimerViewp->getTime(LLFastTimer::FTM_NETWORK);
  495. setStat(ST_UPDATE_SECS, idle_secs - network_secs);
  496. setStat(ST_NETWORK_SECS, network_secs);
  497. setStat(ST_IMAGE_SECS,
  498. gFastTimerViewp->getTime(LLFastTimer::FTM_IMAGE_UPDATE));
  499. setStat(ST_REBUILD_SECS,
  500. gFastTimerViewp->getTime(LLFastTimer::FTM_STATESORT));
  501. setStat(ST_RENDER_SECS,
  502. gFastTimerViewp->getTime(LLFastTimer::FTM_RENDER_GEOMETRY));
  503. }
  504. #endif
  505. LLCircuitData* cdp = NULL;
  506. LLViewerRegion* regionp = gAgent.getRegion();
  507. if (regionp)
  508. {
  509. cdp = gMessageSystemp->mCircuitInfo.findCircuit(regionp->getHost());
  510. }
  511. if (cdp)
  512. {
  513. mSimPingStat.addValue(cdp->getPingDelay());
  514. gAvgSimPing = (gAvgSimPing * (F32)gSimPingCount + (F32)cdp->getPingDelay()) /
  515. ((F32)gSimPingCount + 1);
  516. ++gSimPingCount;
  517. }
  518. else
  519. {
  520. mSimPingStat.addValue(10000);
  521. }
  522. mFPSStat.addValue(1);
  523. F32 layer_bits = (F32)(gVLManager.getLandBits() +
  524. gVLManager.getWindBits() +
  525. gVLManager.getCloudBits());
  526. mLayersKBitStat.addValue(layer_bits / 1024.f);
  527. mObjectKBitStat.addValue(gObjectBits / 1024.f);
  528. mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET) / 1024.f);
  529. gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
  530. static LLCachedControl<U32> low_water(gSavedSettings,
  531. "TexFetchingTimerThreshold");
  532. if (gTextureFetchp &&
  533. gTextureFetchp->getApproxNumRequests() <= (U32)low_water)
  534. {
  535. gTextureTimer.pause();
  536. }
  537. else
  538. {
  539. gTextureTimer.unpause();
  540. }
  541. {
  542. static F32 visible_avatar_frames = 0.f;
  543. static F32 avg_visible_avatars = 0;
  544. F32 visible_avatars = (F32)LLVOAvatar::sNumVisibleAvatars;
  545. if (visible_avatars > 0.f)
  546. {
  547. visible_avatar_frames = 1.f;
  548. avg_visible_avatars = (avg_visible_avatars *
  549. (F32)(visible_avatar_frames - 1.f) +
  550. visible_avatars) / visible_avatar_frames;
  551. }
  552. setStat(ST_VISIBLE_AVATARS, (F64)avg_visible_avatars);
  553. }
  554. gWorld.updateNetStats();
  555. gWorld.requestCacheMisses();
  556. // Reset all of these values.
  557. gVLManager.resetBitCounts();
  558. gObjectBits = 0;
  559. // Only update texture stats periodically so that they are less noisy
  560. {
  561. constexpr F32 texture_stats_freq = 1.f;
  562. static LLFrameTimer texture_stats_timer;
  563. if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
  564. {
  565. mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits / 1024.f);
  566. mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
  567. gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
  568. LLViewerTextureList::sTextureBits = 0;
  569. LLViewerTextureList::sTexturePackets = 0;
  570. texture_stats_timer.reset();
  571. }
  572. }
  573. }
  574. void LLViewerStats::sendStats()
  575. {
  576. const std::string& url = gAgent.getRegionCapability("ViewerStats");
  577. if (url.empty())
  578. {
  579. if (gIsInSecondLife)
  580. {
  581. // Capabilities still in flight ?... Retry a bit later.
  582. mNextStatsSendingTime = gFrameTimeSeconds +
  583. SEND_STATS_PERIOD / 5;
  584. llwarns << "Could not get ViewerStats capability" << llendl;
  585. }
  586. else
  587. {
  588. // Retry later, just in case, but OpenSim normally do not
  589. // provide this capability.
  590. mNextStatsSendingTime = gFrameTimeSeconds + SEND_STATS_PERIOD;
  591. }
  592. return;
  593. }
  594. llinfos << "Transmitting sessions stats" << llendl;
  595. LLSD body;
  596. body["session_id"] = gAgentSessionID;
  597. LLSD& agent = body["agent"];
  598. time_t ltime;
  599. time(&ltime);
  600. F32 run_time = (F32)LLFrameTimer::getElapsedSeconds();
  601. agent["start_time"] = S32(ltime - (time_t)run_time);
  602. // The first stat set must have a 0 run time if it doesn't actually contain
  603. // useful data in terms of FPS, etc. We use half the SEND_STATS_PERIOD
  604. // seconds as the point at which these statistics become valid. Data
  605. // warehouse uses a 0 value here to easily discard these records with
  606. // non-useful FPS values etc.
  607. if (run_time < SEND_STATS_PERIOD / 2)
  608. {
  609. agent["run_time"] = 0.f;
  610. }
  611. else
  612. {
  613. agent["run_time"] = run_time;
  614. }
  615. // Send FPS only for the time spent as a foreground application.
  616. F32 foreground_time = gForegroundTime.getElapsedTimeF32();
  617. if (foreground_time > 0.f)
  618. {
  619. F32 fps = F32(gForegroundFrameCount) / foreground_time;
  620. agent["fps"] = fps;
  621. // Let's also inform the server about any FPS limiting in force. This
  622. // is for now an unofficial stats and specific to the Cool VL Viewer,
  623. // but maybe LL will be interested in using it and generalizing it. HB
  624. static LLCachedControl<U32> max_fps(gSavedSettings, "FrameRateLimit");
  625. static LLCachedControl<bool> no_vsync(gSavedSettings,
  626. "DisableVerticalSync");
  627. std::string fps_limit;
  628. if (max_fps >= 20)
  629. {
  630. fps_limit = llformat("%d fps", S32(max_fps));
  631. }
  632. if (!no_vsync)
  633. {
  634. if (!fps_limit.empty())
  635. {
  636. fps_limit += ", ";
  637. }
  638. fps_limit += "vsync";
  639. }
  640. if (fps_limit.empty())
  641. {
  642. fps_limit = "none";
  643. }
  644. agent["fps_limiting"] = fps_limit;
  645. llinfos << "Average FPS rate since session start with window in foreground: "
  646. << fps << " - Current FPS rate limiting: " << fps_limit
  647. << llendl;
  648. }
  649. agent["version"] = gCurrentVersion;
  650. std::string language = LLUI::getLanguage();
  651. agent["language"] = language;
  652. agent["sim_fps"] = ((F32)gFrameCount - gSimFrames) /
  653. (F32)(gRenderStartTime.getElapsedTimeF32() - gSimLastTime);
  654. gSimLastTime = gRenderStartTime.getElapsedTimeF32();
  655. gSimFrames = (F32)gFrameCount;
  656. agent["agents_in_view"] = LLVOAvatar::sNumVisibleAvatars;
  657. agent["ping"] = gAvgSimPing;
  658. agent["meters_traveled"] = gAgent.getDistanceTraveled();
  659. agent["regions_visited"] = gAgent.getRegionsVisited();
  660. agent["mem_use"] = LLMemory::getCurrentRSS() / 1024.0;
  661. // Let's cache this non-varying data... HB
  662. static LLSD system;
  663. if (system.isUndefined())
  664. {
  665. system["ram"] = (S32)LLMemory::getPhysicalMemoryKB();
  666. system["os"] = LLOSInfo::getInstance()->getOSStringSimple();
  667. LLCPUInfo* cpuinfo = LLCPUInfo::getInstance();
  668. system["cpu"] = cpuinfo->getCPUString();
  669. system["cpu_sse"] = cpuinfo->getSSEVersions();
  670. // This is now *always* 64 bits for the Cool VL Viewer
  671. system["address_size"] = 64;
  672. system["os_bitness"] = 64;
  673. system["hardware_concurrency"] = (S32)cpuinfo->getPhysicalCores();
  674. std::string mac_string = llformat("%02x-%02x-%02x-%02x-%02x-%02x",
  675. gMACAddress[0], gMACAddress[1],
  676. gMACAddress[2], gMACAddress[3],
  677. gMACAddress[4], gMACAddress[5]);
  678. system["mac_address"] = mac_string;
  679. system["serial_number"] = gAppViewerp->getSerialNumber();
  680. std::string gpu_desc =
  681. llformat("%-6s Class %d ",
  682. gGLManager.mGLVendorShort.substr(0,6).c_str(),
  683. (S32)gFeatureManager.getGPUClass()) +
  684. gFeatureManager.getGPUString();
  685. system["gpu"] = gpu_desc;
  686. system["gpu_class"] = (S32)gFeatureManager.getGPUClass();
  687. F32 bw = gFeatureManager.getGPUMemoryBandwidth();
  688. if (bw > 0.f)
  689. {
  690. system["gpu_memory_bandwidth"] = bw;
  691. }
  692. system["gpu_vendor"] = gGLManager.mGLVendorShort;
  693. system["gpu_version"] = gGLManager.mDriverVersionVendorString;
  694. system["opengl_version"] = gGLManager.mGLVersionString;
  695. gGLManager.asLLSD(system["gl"]);
  696. }
  697. body["system"] = system;
  698. S32 shader_level = 0;
  699. if (LLPipeline::sRenderDeferred)
  700. {
  701. if (LLPipeline::RenderShadowDetail)
  702. {
  703. shader_level = 5;
  704. }
  705. else if (LLPipeline::RenderDeferredSSAO)
  706. {
  707. shader_level = 4;
  708. }
  709. else
  710. {
  711. shader_level = 3;
  712. }
  713. }
  714. else if (gPipeline.canUseWindLightShaders())
  715. {
  716. shader_level = 2;
  717. }
  718. else if (gPipeline.shadersLoaded())
  719. {
  720. shader_level = 1;
  721. }
  722. system["shader_level"] = shader_level;
  723. LLSD& download = body["downloads"];
  724. download["world_kbytes"] = gTotalWorldBytes / 1024.0;
  725. download["object_kbytes"] = gTotalObjectBytes / 1024.0;
  726. download["texture_kbytes"] = gTotalTextureBytes / 1024.0;
  727. download["mesh_kbytes"] = LLMeshRepository::sBytesReceived / 1024.0;
  728. LLMessageSystem* msg = gMessageSystemp;
  729. LLSD& in = body["stats"]["net"]["in"];
  730. in["kbytes"] = msg->mTotalBytesIn / 1024.0;
  731. in["packets"] = (S32)msg->mPacketsIn;
  732. in["compressed_packets"] = (S32)msg->mCompressedPacketsIn;
  733. in["savings"] = (msg->mUncompressedBytesIn -
  734. msg->mCompressedBytesIn) / 1024.0;
  735. LLSD& out = body["stats"]["net"]["out"];
  736. out["kbytes"] = msg->mTotalBytesOut / 1024.0;
  737. out["packets"] = (S32)msg->mPacketsOut;
  738. out["compressed_packets"] = (S32)msg->mCompressedPacketsOut;
  739. out["savings"] = (msg->mUncompressedBytesOut -
  740. msg->mCompressedBytesOut) / 1024.0;
  741. LLSD& fail = body["stats"]["failures"];
  742. fail["send_packet"] = (S32)msg->mSendPacketFailureCount;
  743. fail["dropped"] = (S32)msg->mDroppedPackets;
  744. fail["resent"] = (S32)msg->mResentPackets;
  745. fail["failed_resends"] = (S32)msg->mFailedResendPackets;
  746. fail["off_circuit"] = (S32)msg->mOffCircuitPackets;
  747. fail["invalid"] = (S32)msg->mInvalidOnCircuitPackets;
  748. // Misc stats, two strings and two ints. These are not expected to persist
  749. // across multiple releases. Comment any changes with your name and the
  750. // expected release revision. If the current revision is recent, ping the
  751. // previous author before overriding.
  752. LLSD& misc = body["stats"]["misc"];
  753. #if LL_DARWIN
  754. // No Vulkan driver detection code for macOS... *TODO: detect MoltenVK ?
  755. misc["string_1"] = "";
  756. #else
  757. std::string version;
  758. if (gAppViewerp->probeVulkan(version))
  759. {
  760. misc["string_1"] = "Vulkan driver is detected";
  761. misc["VulkanMaxApiVersion"] = version;
  762. }
  763. else
  764. {
  765. misc["string_1"] = "No Vulkan driver detected";
  766. }
  767. #endif
  768. if (gFrameTimeSeconds > 0)
  769. {
  770. misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f",
  771. gTextureTimer.getElapsedTimeF32(),
  772. gFrameTimeSeconds);
  773. }
  774. else
  775. {
  776. misc["string_2"] = "Unused";
  777. }
  778. F32 unbaked_time = LLVOAvatar::sUnbakedTime * 1000.f / gFrameTimeSeconds;
  779. misc["int_1"] = LLSD::Integer(unbaked_time); // Steve: 1.22
  780. F32 grey_time = LLVOAvatar::sGreyTime * 1000.f / gFrameTimeSeconds;
  781. misc["int_2"] = LLSD::Integer(grey_time); // Steve: 1.22
  782. llinfos << "Misc stats: int_1: " << misc["int_1"].asInteger()
  783. << " - int_2: " << misc["int_2"].asInteger() << llendl;
  784. llinfos << "Misc stats: string_1: " << misc["string_1"].asString()
  785. << " - string_2: " << misc["string_2"].asString() << llendl;
  786. U32 display_names_usage = LLAvatarNameCache::useDisplayNames();
  787. body["DisplayNamesEnabled"] = display_names_usage != 0;
  788. // The Cool VL Viewer actually shows legacy names, never user names...
  789. body["DisplayNamesShowUsername"] = display_names_usage != 2;
  790. addToMessage(body);
  791. LL_DEBUGS("ViewerStats") << "Sending stats:\n" << ll_pretty_print_sd(body)
  792. << LL_ENDL;
  793. LLCoreHttpUtil::HttpCoroutineAdapter::messageHttpPost(url, body,
  794. "Statistics posted to sim",
  795. "Failed to post statistics to sim");
  796. mNextStatsSendingTime = gFrameTimeSeconds + SEND_STATS_PERIOD;
  797. }
  798. void LLViewerStats::resetAvatarStats()
  799. {
  800. mNextAvStatsSendingTime = gFrameTimeSeconds + SEND_AVATAR_STATS_PERIOD;
  801. mComplexityReports = mTooComplexReports = 0;
  802. }
  803. void LLViewerStats::avatarRenderingStats()
  804. {
  805. mComplexityReports = mTooComplexReports = 0;
  806. LLViewerRegion* regionp = gAgent.getRegion();
  807. if (!regionp) return;
  808. // Unlike LL's lame code we limit ourselves to our region and neighbouring
  809. // regions (since anyway avatars beyond these are not fully rendered, when
  810. // at all). HB
  811. std::vector<LLViewerRegion*> regions;
  812. regions.push_back(regionp);
  813. regionp->getNeighboringRegions(regions);
  814. // Construct a map of <regionp, cap_url> with live regions actually having
  815. // the necessary capability.
  816. fast_hmap<LLViewerRegion*, std::string> regions_cap;
  817. for (S32 i = 0, count = regions.size(); i < count; ++i)
  818. {
  819. regionp = regions[i];
  820. if (regionp && regionp->isAlive() && regionp->capabilitiesReceived())
  821. {
  822. const std::string& url =
  823. regionp->getCapability("AvatarRenderInfo");
  824. if (!url.empty())
  825. {
  826. regions_cap.emplace(regionp, url);
  827. }
  828. }
  829. }
  830. if (regions_cap.empty())
  831. {
  832. // Do not bother...
  833. mNextAvStatsSendingTime = gFrameTimeSeconds + SEND_AVATAR_STATS_PERIOD;
  834. return;
  835. }
  836. // Construct a LLSD with all avatars we got a complexity for, in our own
  837. // and all neighbouring regions that got the necessary capability. Unlike
  838. // LL's lame code, we scan the characters list only once for all regions
  839. // (instead of once per region !). HB
  840. LLSD data = LLSD::emptyMap();
  841. for (S32 i = 0, count = LLCharacter::sInstances.size(); i < count; ++i)
  842. {
  843. LLVOAvatar* avatarp = (LLVOAvatar*)LLCharacter::sInstances[i];
  844. if (avatarp && !avatarp->isDead() && !avatarp->mIsDummy &&
  845. !avatarp->isOrphaned() && avatarp->isFullyLoaded(true))
  846. {
  847. regionp = avatarp->getRegion();
  848. if (!regionp || !regions_cap.count(regionp)) continue;
  849. U32 complexity = avatarp->getVisualComplexity();
  850. if (complexity)
  851. {
  852. LLSD info = LLSD::emptyMap();
  853. if (complexity > (U32)S32_MAX) // very unlikely...
  854. {
  855. complexity = S32_MAX;
  856. }
  857. info[KEY_WEIGHT] = LLSD::Integer(complexity);
  858. info[KEY_TOO_COMPLEX] = LLSD::Boolean(avatarp->isTooComplex());
  859. const LLUUID& rg_id = regionp->getRegionID();
  860. const LLUUID& av_id = avatarp->getID();
  861. data[rg_id.asString()][KEY_AGENTS][av_id.asString()] = info;
  862. }
  863. }
  864. }
  865. // Send the stats request and report (if any for the latter) for the
  866. // concerned regions. HB
  867. for (fast_hmap<LLViewerRegion*, std::string>::const_iterator
  868. it = regions_cap.begin(), end = regions_cap.end();
  869. it != end; ++it)
  870. {
  871. regionp = it->first;
  872. const std::string& url = it->second;
  873. gCoros.launch("LLViewerStats::getAvatarRenderStatsCoro",
  874. boost::bind(&LLViewerStats::getAvatarRenderStatsCoro, url,
  875. regionp->getName()));
  876. std::string region_id_str = regionp->getRegionID().asString();
  877. if (!data.has(region_id_str)) continue;
  878. gCoros.launch("LLViewerStats::sendAvatarRenderStatsCoro",
  879. boost::bind(&LLViewerStats::sendAvatarRenderStatsCoro,
  880. url, regionp->getName(),
  881. data[region_id_str]));
  882. }
  883. mNextAvStatsSendingTime = gFrameTimeSeconds + SEND_AVATAR_STATS_PERIOD;
  884. }
  885. //static
  886. void LLViewerStats::getAvatarRenderStatsCoro(const std::string& url,
  887. std::string region_name)
  888. {
  889. if (url.empty()) return;
  890. LLCoreHttpUtil::HttpCoroutineAdapter adapter("getAvatarRenderStats");
  891. LLSD result = adapter.getAndSuspend(url);
  892. LLCore::HttpStatus status =
  893. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  894. if (!status)
  895. {
  896. llwarns << "HTTP error getting avatar rendering stats for region '"
  897. << region_name << "'. Status: " << status.toString() << llendl;
  898. return;
  899. }
  900. #if 0 // Not really useful...
  901. else if (result.isMap() && result.has(KEY_AGENTS))
  902. {
  903. const LLSD& agents = result[KEY_AGENTS];
  904. if (agents.isMap())
  905. {
  906. for (LLSD::map_const_iterator it = agents.beginMap(),
  907. end = agents.endMap();
  908. it != end; ++it)
  909. {
  910. LLUUID agent_id(it->first);
  911. LLVOAvatar* avatarp = gObjectList.findAvatar(agent_id);
  912. if (avatarp)
  913. {
  914. const LLSD& agent_info_map = it->second;
  915. if (agent_info_map.isMap())
  916. {
  917. LL_DEBUGS("ViewerStats") << "Agent " << target_agent_id
  918. << ": " << agent_info_map
  919. << LL_ENDL;
  920. }
  921. }
  922. }
  923. }
  924. }
  925. #endif
  926. if (result.has(KEY_REPORTING_COMPLEXITY_LIMIT) &&
  927. result.has(KEY_OVER_COMPLEXITY_LIMIT))
  928. {
  929. U32 reporting = result[KEY_REPORTING_COMPLEXITY_LIMIT].asInteger();
  930. gViewerStats.mComplexityReports += reporting;
  931. U32 overlimit = result[KEY_OVER_COMPLEXITY_LIMIT].asInteger();
  932. gViewerStats.mTooComplexReports += overlimit;
  933. if (reporting != 0 || overlimit != 0)
  934. {
  935. llinfos << "Complexity reports: "
  936. << gViewerStats.mComplexityReports
  937. << " - Too complex reports: "
  938. << gViewerStats.mTooComplexReports
  939. << llendl;
  940. }
  941. }
  942. else
  943. {
  944. llwarns << "Malformed response to the last avatar rendering stats query in region: "
  945. << region_name << ":\n" << result.asString() << llendl;
  946. }
  947. }
  948. //static
  949. void LLViewerStats::sendAvatarRenderStatsCoro(const std::string& url,
  950. std::string region_name,
  951. const LLSD& data)
  952. {
  953. if (url.empty()) return;
  954. LLCoreHttpUtil::HttpCoroutineAdapter adapter("sendAvatarRenderStats");
  955. LLSD result = adapter.postAndSuspend(url, data);
  956. LLCore::HttpStatus status =
  957. LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(result);
  958. if (!status)
  959. {
  960. llwarns << "HTTP error sending avatar rendering stats for region '"
  961. << region_name << "'. Status: " << status.toString() << llendl;
  962. }
  963. else if (result.isMap() && result.has(KEY_ERROR))
  964. {
  965. const LLSD& error = result[KEY_ERROR];
  966. llwarns << "Error sending avatar rendering stats for region '"
  967. << region_name << "': " << error[KEY_MESSAGE] << llendl;
  968. }
  969. else
  970. {
  971. LL_DEBUGS("ViewerStats") << "result for avatar rendering stats sending to region: "
  972. << region_name << ":\n" << result.asString()
  973. << LL_ENDL;
  974. }
  975. }
  976. void output_statistics(void*)
  977. {
  978. llinfos << "--------------------------------" << llendl;
  979. llinfos << "Objects:" << llendl;
  980. llinfos << "--------------------------------" << llendl;
  981. S32 num_objects = LLViewerObject::getNumObjects();
  982. llinfos << "Number of Viewer Objects in memory: " << num_objects << llendl;
  983. S32 listed_objects = gObjectList.getNumObjects();
  984. llinfos << "Number of objects in list: " << listed_objects << llendl;
  985. llinfos << "Zombie Viewer Objects: " << num_objects - listed_objects
  986. << llendl;
  987. llinfos << "Number of dead objects: " << gObjectList.getNumDeadObjects()
  988. << llendl;
  989. llinfos << "Number of orphans: " << gObjectList.getOrphanCount() << llendl;
  990. LLVolumeImplFlexible::dumpStats();
  991. llinfos << "--------------------------------" << llendl;
  992. llinfos << "Images:" << llendl;
  993. llinfos << "--------------------------------" << llendl;
  994. llinfos << "Num images: " << gTextureList.getNumImages() << llendl;
  995. llinfos << "Texture usage: " << LLImageGL::sGlobalTexMemBytes << llendl;
  996. llinfos << "Bound textures usage: " << LLImageGL::sBoundTexMemBytes
  997. << llendl;
  998. LLImage::dumpStats();
  999. LLViewerTextureAnim::dumpStats();
  1000. llinfos << "--------------------------------" << llendl;
  1001. llinfos << "Lights:" << llendl;
  1002. llinfos << "--------------------------------" << llendl;
  1003. llinfos << "Number of lights: " << gPipeline.getLightCount() << llendl;
  1004. llinfos << "--------------------------------" << llendl;
  1005. llinfos << "Memory Usage:" << llendl;
  1006. llinfos << "--------------------------------" << llendl;
  1007. LLMemory::logMemoryInfo();
  1008. llinfos << "--------------------------------" << llendl;
  1009. llinfos << "Pipeline:" << llendl;
  1010. llinfos << "--------------------------------" << llendl;
  1011. gPipeline.dumpStats();
  1012. llinfos << "--------------------------------" << llendl;
  1013. llinfos << "Characters and motion controller:" << llendl;
  1014. llinfos << "--------------------------------" << llendl;
  1015. LLCharacter::dumpStats();
  1016. LLMotionController::dumpStats();
  1017. llinfos << "--------------------------------" << llendl;
  1018. llinfos << "Avatar Memory (partly overlaps with above stats):" << llendl;
  1019. llinfos << "--------------------------------" << llendl;
  1020. gTexLayerStaticImageList.dumpByteCount();
  1021. LLViewerTexLayerSetBuffer::dumpTotalByteCount();
  1022. LLVOAvatarSelf::dumpTotalLocalTextureByteCount();
  1023. LLTexLayerParamAlpha::dumpCacheByteCount();
  1024. LLVOAvatar::dumpBakedStatus();
  1025. llinfos << llendl;
  1026. llinfos << "Object counts:" << llendl;
  1027. S32 obj_counts[256];
  1028. for (S32 i = 0; i < 256; ++i)
  1029. {
  1030. obj_counts[i] = 0;
  1031. }
  1032. for (S32 i = 0, count = gObjectList.getNumObjects(); i < count; ++i)
  1033. {
  1034. LLViewerObject* objectp = gObjectList.getObject(i);
  1035. if (objectp)
  1036. {
  1037. ++obj_counts[objectp->getPCode()];
  1038. }
  1039. }
  1040. for (S32 i = 0; i < 256; ++i)
  1041. {
  1042. if (obj_counts[i])
  1043. {
  1044. llinfos << LLPrimitive::pCodeToString(i) << ":" << obj_counts[i]
  1045. << llendl;
  1046. }
  1047. }
  1048. llinfos << "--------------------------------" << llendl;
  1049. }