From c799f9f7ebca856889600a82ac12ac9256a876ee Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:46:31 -0600 Subject: [PATCH 01/18] Avoid sculpt discard-level 5 spam. --- indra/newview/llvovolume.cpp | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index bd3fb344a..2af2dc14b 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -926,20 +926,32 @@ void LLVOVolume::sculpt() if (discard_level > max_discard) discard_level = max_discard; // clamp to the best we can do - S32 current_discard = getVolume()->getSculptLevel(); + S32 current_discard = getVolume()->getSculptLevel() ; if(current_discard < -2) { - llwarns << "WARNING!!: Current discard of sculpty at " << current_discard - << " is less than -2." << llendl; + static S32 low_sculpty_discard_warning_count = 100; + if (++low_sculpty_discard_warning_count >= 100) + { // Log first time, then every 100 afterwards otherwise this can flood the logs + llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is less than -2." << llendl; + low_sculpty_discard_warning_count = 0; + } // corrupted volume... don't update the sculpty return; } else if (current_discard > MAX_DISCARD_LEVEL) { - llwarns << "WARNING!!: Current discard of sculpty at " << current_discard - << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; - + static S32 high_sculpty_discard_warning_count = 100; + if (++high_sculpty_discard_warning_count >= 100) + { // Log first time, then every 100 afterwards otherwise this can flood the logs + llwarns << "WARNING!!: Current discard for sculpty " << mSculptTexture->getID() + << " at " << current_discard + << " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; + high_sculpty_discard_warning_count = 0; + } + // corrupted volume... don't update the sculpty return; } From 0759f2dae8508d26bf60288b688142159fd56240 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:47:59 -0600 Subject: [PATCH 02/18] Actually use the namecache callback results when displaying currency transaction notifications. --- indra/newview/llviewermessage.cpp | 42 ++++++++++++------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index b0395da79..eabb0a7c5 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5799,6 +5799,18 @@ static std::string reason_from_transaction_type(S32 transaction_type, } } +static void process_money_group_name_reply(const std::string& name, const std::string notification, LLSD args, LLSD payload) +{ + args["NAME"] = name; + LLNotificationsUtil::add(notification,args,payload); +} +static void process_money_avatar_name_reply(const LLAvatarName& name, const std::string notification, LLSD args, LLSD payload) +{ + std::string av_name; + LLAvatarNameCache::getPNSName(name,av_name); + args["NAME"] = av_name; + LLNotificationsUtil::add(notification,args,payload); +} static void process_money_balance_reply_extended(LLMessageSystem* msg) { // Added in server 1.40 and viewer 2.1, support for localization @@ -5831,26 +5843,6 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) return; } - std::string source_slurl; - if (is_source_group) - { - gCacheName->getGroupName(source_id, source_slurl); - } - else - { - LLAvatarNameCache::getPNSName(source_id, source_slurl); - } - - std::string dest_slurl; - if (is_dest_group) - { - gCacheName->getGroupName(dest_id, dest_slurl); - } - else - { - LLAvatarNameCache::getPNSName(dest_id, dest_slurl); - } - std::string reason = reason_from_transaction_type(transaction_type, item_description); @@ -5871,7 +5863,6 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) bool you_paid_someone = (source_id == gAgentID); if (you_paid_someone) { - args["NAME"] = dest_slurl; is_name_group = is_dest_group; name_id = dest_id; if (!reason.empty()) @@ -5907,7 +5898,6 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) else { // ...someone paid you - args["NAME"] = source_slurl; is_name_group = is_source_group; name_id = source_id; if (!reason.empty()) @@ -5930,14 +5920,14 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) if (is_name_group) { gCacheName->getGroup(name_id, - boost::bind(&LLNotificationsUtil::add, - notification, final_args, payload)); + boost::bind(&process_money_group_name_reply, + _2, notification, final_args, payload)); } else { LLAvatarNameCache::get(name_id, - boost::bind(&LLNotificationsUtil::add, - notification, final_args, payload)); + boost::bind(&process_money_avatar_name_reply, + _2, notification, final_args, payload)); } } From 5180fbfc23e0ce73b5c8664c928518833b011db4 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:50:29 -0600 Subject: [PATCH 03/18] Clean up llfloaterurlentry --- indra/newview/llfloaterurlentry.cpp | 67 ++++++++++++++--------------- indra/newview/llfloaterurlentry.h | 2 +- 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/indra/newview/llfloaterurlentry.cpp b/indra/newview/llfloaterurlentry.cpp index 122cfd60f..dd6ea2864 100644 --- a/indra/newview/llfloaterurlentry.cpp +++ b/indra/newview/llfloaterurlentry.cpp @@ -103,27 +103,6 @@ LLFloaterURLEntry::LLFloaterURLEntry(LLHandle parent) mPanelLandMediaHandle(parent) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml"); - - mMediaURLEdit = getChild("media_entry"); - - // Cancel button - childSetAction("cancel_btn", onBtnCancel, this); - - // Cancel button - childSetAction("clear_btn", onBtnClear, this); - - // clear media list button - LLSD parcel_history = LLURLHistory::getURLHistory("parcel"); - bool enable_clear_button = parcel_history.size() > 0 ? true : false; - childSetEnabled( "clear_btn", enable_clear_button ); - - // OK button - childSetAction("ok_btn", onBtnOK, this); - - setDefaultBtn("ok_btn"); - buildURLHistory(); - - sInstance = this; } //----------------------------------------------------------------------------- @@ -134,6 +113,28 @@ LLFloaterURLEntry::~LLFloaterURLEntry() sInstance = NULL; } +BOOL LLFloaterURLEntry::postBuild() +{ + mMediaURLEdit = getChild("media_entry"); + + // Cancel button + childSetAction("cancel_btn", onBtnCancel, this); + + // Cancel button + childSetAction("clear_btn", onBtnClear, this); + // clear media list button + LLSD parcel_history = LLURLHistory::getURLHistory("parcel"); + bool enable_clear_button = parcel_history.size() > 0 ? true : false; + getChildView("clear_btn")->setEnabled(enable_clear_button ); + + // OK button + childSetAction("ok_btn", onBtnOK, this); + + setDefaultBtn("ok_btn"); + buildURLHistory(); + + return TRUE; +} void LLFloaterURLEntry::buildURLHistory() { LLCtrlListInterface* url_list = childGetListInterface("media_entry"); @@ -157,7 +158,7 @@ void LLFloaterURLEntry::buildURLHistory() void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type) { - LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get(); + LLPanelLandMedia* panel_media = dynamic_cast(mPanelLandMediaHandle.get()); if (panel_media) { // status is ignored for now -- error = "none/none" @@ -166,21 +167,18 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_ } // Decrement the cursor getWindow()->decBusyCount(); - childSetVisible("loading_label", false); + getChildView("loading_label")->setVisible( false); close(); } // static LLHandle LLFloaterURLEntry::show(LLHandle parent) { - if (sInstance) - { - sInstance->open(); - } - else + if (!sInstance) { sInstance = new LLFloaterURLEntry(parent); } + sInstance->open(); sInstance->updateFromLandMediaPanel(); return sInstance->getHandle(); } @@ -239,7 +237,8 @@ void LLFloaterURLEntry::onBtnOK( void* userdata ) } // Discover the MIME type only for "http" scheme. - if(scheme == "http" || scheme == "https") + if(!media_url.empty() && + (scheme == "http" || scheme == "https")) { LLHTTPClient::getHeaderOnly( media_url, new LLMediaTypeResponder(self->getHandle())); @@ -250,13 +249,13 @@ void LLFloaterURLEntry::onBtnOK( void* userdata ) } // Grey the buttons until we get the header response - self->childSetEnabled("ok_btn", false); - self->childSetEnabled("cancel_btn", false); - self->childSetEnabled("media_entry", false); + self->getChildView("ok_btn")->setEnabled(false); + self->getChildView("cancel_btn")->setEnabled(false); + self->getChildView("media_entry")->setEnabled(false); // show progress bar here? getWindow()->incBusyCount(); - self->childSetVisible("loading_label", true); + self->getChildView("loading_label")->setVisible( true); } // static @@ -298,7 +297,7 @@ bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const LLURLHistory::clear("parcel"); // cleared the list so disable Clear button - childSetEnabled( "clear_btn", false ); + getChildView("clear_btn")->setEnabled(false ); } return false; } diff --git a/indra/newview/llfloaterurlentry.h b/indra/newview/llfloaterurlentry.h index dbc345a1c..0aeca823b 100644 --- a/indra/newview/llfloaterurlentry.h +++ b/indra/newview/llfloaterurlentry.h @@ -45,7 +45,7 @@ public: // Can only be shown by LLPanelLandMedia, and pushes data back into // that panel via the handle. static LLHandle show(LLHandle panel_land_media_handle); - + /*virtual*/ BOOL postBuild(); void updateFromLandMediaPanel(); void headerFetchComplete(U32 status, const std::string& mime_type); From 0a8147a9dafcde49e1981fcd5c8052bc094c741c Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:52:53 -0600 Subject: [PATCH 04/18] Merged some alignment adjustments from sunshine-external --- indra/llappearance/lldriverparam.h | 5 +++-- indra/llappearance/llpolymorph.h | 6 ++++-- indra/llappearance/llpolyskeletaldistortion.h | 5 +++-- indra/llappearance/lltexlayerparams.h | 18 +++++++++++------- indra/llappearance/llviewervisualparam.h | 3 ++- 5 files changed, 23 insertions(+), 14 deletions(-) diff --git a/indra/llappearance/lldriverparam.h b/indra/llappearance/lldriverparam.h index 1a24cefa1..65dd3cdde 100644 --- a/indra/llappearance/lldriverparam.h +++ b/indra/llappearance/lldriverparam.h @@ -76,6 +76,7 @@ protected: //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLDriverParam : public LLViewerVisualParam { friend class LLPhysicsMotion; @@ -133,13 +134,13 @@ protected: void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); - LLVector4a mDefaultVec; // temp holder + LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder typedef std::vector entry_list_t; entry_list_t mDriven; LLViewerVisualParam* mCurrentDistortionParam; // Backlink only; don't make this an LLPointer. LLAvatarAppearance* mAvatarAppearance; LLWearable* mWearablep; -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLDRIVERPARAM_H diff --git a/indra/llappearance/llpolymorph.h b/indra/llappearance/llpolymorph.h index f7782ffb3..03915d3da 100644 --- a/indra/llappearance/llpolymorph.h +++ b/indra/llappearance/llpolymorph.h @@ -41,6 +41,7 @@ class LLWearable; //----------------------------------------------------------------------------- // LLPolyMorphData() //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLPolyMorphData { public: @@ -79,12 +80,13 @@ public: F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mMaxDistortion; // maximum single vertex distortion in a given morph - LLVector4a mAvgDistortion; // average vertex distortion, to infer directionality of the morph + LL_ALIGN_16(LLVector4a mAvgDistortion); // average vertex distortion, to infer directionality of the morph LLPolyMeshSharedData* mMesh; private: void freeData(); -}; +} LL_ALIGN_POSTFIX(16); + //----------------------------------------------------------------------------- // LLPolyVertexMask() diff --git a/indra/llappearance/llpolyskeletaldistortion.h b/indra/llappearance/llpolyskeletaldistortion.h index b9c3c3628..774bc7dfa 100644 --- a/indra/llappearance/llpolyskeletaldistortion.h +++ b/indra/llappearance/llpolyskeletaldistortion.h @@ -63,6 +63,7 @@ struct LLPolySkeletalBoneInfo BOOL mHasPositionDeformation; }; +LL_ALIGN_PREFIX(16) class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo { friend class LLPolySkeletalDistortion; @@ -118,13 +119,13 @@ public: /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; protected: + LL_ALIGN_16(LLVector4a mDefaultVec); typedef std::map joint_vec_map_t; joint_vec_map_t mJointScales; joint_vec_map_t mJointOffsets; - LLVector4a mDefaultVec; // Backlink only; don't make this an LLPointer. LLAvatarAppearance *mAvatar; -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLPOLYSKELETALDISTORTION_H diff --git a/indra/llappearance/lltexlayerparams.h b/indra/llappearance/lltexlayerparams.h index ca1497ebf..b38d28d3e 100644 --- a/indra/llappearance/lltexlayerparams.h +++ b/indra/llappearance/lltexlayerparams.h @@ -60,6 +60,7 @@ protected: // LLTexLayerParamAlpha // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +LL_ALIGN_PREFIX(16) class LLTexLayerParamAlpha : public LLTexLayerParam { public: @@ -67,8 +68,6 @@ public: LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); /*virtual*/ ~LLTexLayerParamAlpha(); - /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; - void* operator new(size_t size) { return ll_aligned_malloc_16(size); @@ -79,6 +78,8 @@ public: ll_aligned_free_16(ptr); } + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; + // LLVisualParam Virtual functions ///*virtual*/ BOOL parseData(LLXmlTreeNode* node); /*virtual*/ void apply( ESex avatar_sex ) {} @@ -106,7 +107,7 @@ private: LLPointer mStaticImageRaw; BOOL mNeedsCreateTexture; BOOL mStaticImageInvalid; - LLVector4a mAvgDistortionVec; + LL_ALIGN_16(LLVector4a mAvgDistortionVec); F32 mCachedEffectiveWeight; public: @@ -116,7 +117,7 @@ public: typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; static param_alpha_ptr_list_t sInstances; -}; +} LL_ALIGN_POSTFIX(16); class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo { friend class LLTexLayerParamAlpha; @@ -140,6 +141,8 @@ private: // LLTexLayerParamColor // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +LL_ALIGN_PREFIX(16) class LLTexLayerParamColor : public LLTexLayerParam { public: @@ -153,7 +156,6 @@ public: LLTexLayerParamColor( LLTexLayerInterface* layer ); LLTexLayerParamColor( LLAvatarAppearance* appearance ); - /* virtual */ ~LLTexLayerParamColor(); void* operator new(size_t size) { @@ -165,6 +167,8 @@ public: ll_aligned_free_16(ptr); } + /* virtual */ ~LLTexLayerParamColor(); + /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; // LLVisualParam Virtual functions @@ -188,8 +192,8 @@ public: protected: virtual void onGlobalColorChanged(bool upload_bake) {} private: - LLVector4a mAvgDistortionVec; -}; + LL_ALIGN_16(LLVector4a mAvgDistortionVec); +} LL_ALIGN_POSTFIX(16); class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo { diff --git a/indra/llappearance/llviewervisualparam.h b/indra/llappearance/llviewervisualparam.h index 259c0d6ee..64364c881 100644 --- a/indra/llappearance/llviewervisualparam.h +++ b/indra/llappearance/llviewervisualparam.h @@ -66,6 +66,7 @@ protected: // VIRTUAL CLASS // a viewer side interface class for a generalized parametric modification of the avatar mesh //----------------------------------------------------------------------------- +LL_ALIGN_PREFIX(16) class LLViewerVisualParam : public LLVisualParam { public: @@ -106,6 +107,6 @@ public: BOOL getCrossWearable() const { return getInfo()->mCrossWearable; } -}; +} LL_ALIGN_POSTFIX(16); #endif // LL_LLViewerVisualParam_H From 655c9348dec2e90fe724fe9b22b5f15356eadd5e Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:53:56 -0600 Subject: [PATCH 05/18] Minor adjsutment to llcontrolgroup. Demote non-critical failure from llerrs to llwarns. --- indra/llxml/llcontrol.h | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/indra/llxml/llcontrol.h b/indra/llxml/llcontrol.h index 18861cb23..2816918a8 100644 --- a/indra/llxml/llcontrol.h +++ b/indra/llxml/llcontrol.h @@ -99,8 +99,10 @@ typedef enum e_control_type class LLControlVariable : public LLRefCount { - friend class LLControlGroup; + LOG_CLASS(LLControlVariable); + friend class LLControlGroup; + public: typedef boost::signals2::signal validate_signal_t; typedef boost::signals2::signal commit_signal_t; @@ -208,6 +210,7 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro //const U32 STRING_CACHE_SIZE = 10000; class LLControlGroup : public LLInstanceTracker { + LOG_CLASS(LLControlGroup); protected: typedef std::map ctrl_name_table_t; ctrl_name_table_t mNameTable; @@ -283,6 +286,7 @@ public: else { llwarns << "Control " << name << " not found." << llendl; + return T(); } return convert_from_llsd(value, type, name); } @@ -313,7 +317,7 @@ public: } else { - llerrs << "Invalid control " << name << llendl; + llwarns << "Invalid control " << name << llendl; } } From 074261067480e2ba285c63631316cf004c0b8cd0 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 14:59:02 -0600 Subject: [PATCH 06/18] Updated gObjectPreviewProgram shader (simple lighting) --- .../shaders/class1/objects/previewF.glsl | 41 +++++++++++++ .../shaders/class1/objects/previewV.glsl | 57 ++++++++++++++++--- indra/newview/llfloatermodelpreview.cpp | 24 ++++---- indra/newview/llviewershadermgr.cpp | 13 +++-- 4 files changed, 107 insertions(+), 28 deletions(-) create mode 100644 indra/newview/app_settings/shaders/class1/objects/previewF.glsl diff --git a/indra/newview/app_settings/shaders/class1/objects/previewF.glsl b/indra/newview/app_settings/shaders/class1/objects/previewF.glsl new file mode 100644 index 000000000..284da3d0a --- /dev/null +++ b/indra/newview/app_settings/shaders/class1/objects/previewF.glsl @@ -0,0 +1,41 @@ +/** + * @file previewF.glsl + * + * $LicenseInfo:firstyear=2011&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2011, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#ifdef DEFINE_GL_FRAGCOLOR +out vec4 frag_color; +#else +#define frag_color gl_FragColor +#endif + +uniform sampler2D diffuseMap; + +VARYING vec4 vertex_color; +VARYING vec2 vary_texcoord0; + +void main() +{ + vec4 color = texture2D(diffuseMap,vary_texcoord0.xy) * vertex_color; + frag_color = color; +} diff --git a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl index 5dcfa8706..7f3f84398 100644 --- a/indra/newview/app_settings/shaders/class1/objects/previewV.glsl +++ b/indra/newview/app_settings/shaders/class1/objects/previewV.glsl @@ -32,12 +32,51 @@ ATTRIBUTE vec3 position; ATTRIBUTE vec3 normal; ATTRIBUTE vec2 texcoord0; +uniform vec4 color; + VARYING vec4 vertex_color; VARYING vec2 vary_texcoord0; +uniform vec4 light_position[8]; +uniform vec3 light_direction[8]; +uniform vec3 light_attenuation[8]; +uniform vec3 light_diffuse[8]; + +//=================================================================================================== +//declare these here explicitly to separate them from atmospheric lighting elsewhere to work around +//drivers that are picky about functions being declared but not defined even if they aren't called +float calcDirectionalLight(vec3 n, vec3 l) +{ + float a = max(dot(n,l),0.0); + return a; +} + + +float calcPointLightOrSpotLight(vec3 v, vec3 n, vec4 lp, vec3 ln, float la, float is_pointlight) +{ + //get light vector + vec3 lv = lp.xyz-v; + + //get distance + float d = length(lv); + + //normalize light vector + lv *= 1.0/d; + + //distance attenuation + float da = clamp(1.0/(la * d), 0.0, 1.0); + + // spotlight coefficient. + float spot = max(dot(-ln, lv), is_pointlight); + da *= spot*spot; // GL_SPOT_EXPONENT=2 + + //angular attenuation + da *= calcDirectionalLight(n, lv); + + return da; +} +//==================================================================================================== -vec4 calcLighting(vec3 pos, vec3 norm, vec4 color, vec4 baseCol); -void calcAtmospherics(vec3 inPositionEye); void main() { @@ -45,13 +84,15 @@ void main() vec4 pos = (modelview_matrix * vec4(position.xyz, 1.0)); gl_Position = modelview_projection_matrix * vec4(position.xyz, 1.0); vary_texcoord0 = (texture_matrix0 * vec4(texcoord0,0,1)).xy; - + vec3 norm = normalize(normal_matrix * normal); - calcAtmospherics(pos.xyz); + vec4 col = vec4(0,0,0,1); - vec4 color = calcLighting(pos.xyz, norm, vec4(1,1,1,1), vec4(0.)); - vertex_color = color; - - + // Collect normal lights (need to be divided by two, as we later multiply by 2) + col.rgb += light_diffuse[1].rgb * calcDirectionalLight(norm, light_position[1].xyz); + col.rgb += light_diffuse[2].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[2], light_direction[2], light_attenuation[2].x, light_attenuation[2].z); + col.rgb += light_diffuse[3].rgb*calcPointLightOrSpotLight(pos.xyz, norm, light_position[3], light_direction[3], light_attenuation[3].x, light_attenuation[3].z); + + vertex_color = col*color; } diff --git a/indra/newview/llfloatermodelpreview.cpp b/indra/newview/llfloatermodelpreview.cpp index 8ca18f6b0..8ff747187 100644 --- a/indra/newview/llfloatermodelpreview.cpp +++ b/indra/newview/llfloatermodelpreview.cpp @@ -1641,7 +1641,6 @@ bool LLModelLoader::doLoadModel() //If no skeleton, do a breadth-first search to get at specific joints bool rootNode = false; - bool skeletonWithNoRootNode = false; //Need to test for a skeleton that does not have a root node //This occurs when your instance controller does not have an associated scene @@ -1652,10 +1651,6 @@ bool LLModelLoader::doLoadModel() { rootNode = true; } - else - { - skeletonWithNoRootNode = true; - } } if (!pSkeleton || !rootNode) @@ -5034,6 +5029,11 @@ BOOL LLModelPreview::render() refresh(); } + if (use_shaders) + { + gObjectPreviewProgram.bind(); + } + gGL.loadIdentity(); gPipeline.enableLightsPreview(); @@ -5043,8 +5043,9 @@ BOOL LLModelPreview::render() LLQuaternion av_rot = camera_rot; LLViewerCamera::getInstance()->setOriginAndLookAt( target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera - LLVector3::z_axis, // up - target_pos); // point of interest + LLVector3::z_axis, // up + target_pos); // point of interest + z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f); @@ -5058,11 +5059,6 @@ BOOL LLModelPreview::render() const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0; - if (use_shaders) - { - gObjectPreviewProgram.bind(); - } - LLGLEnable normalize(GL_NORMALIZE); if (!mBaseModel.empty() && mVertexBuffer[5].empty()) @@ -5248,10 +5244,10 @@ BOOL LLModelPreview::render() if (i + 1 >= hull_colors.size()) { - hull_colors.push_back(LLColor4U(rand()%128 + 127, rand()%128 + 127, rand()%128 + 127, 128)); + hull_colors.push_back(LLColor4U(rand()%128+127, rand()%128+127, rand()%128+127, 128)); } - glColor4ubv(hull_colors[i].mV); + gGL.diffuseColor4ubv(hull_colors[i].mV); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals); if (explode > 0.f) diff --git a/indra/newview/llviewershadermgr.cpp b/indra/newview/llviewershadermgr.cpp index 313673721..76b3298ec 100644 --- a/indra/newview/llviewershadermgr.cpp +++ b/indra/newview/llviewershadermgr.cpp @@ -1887,18 +1887,19 @@ BOOL LLViewerShaderMgr::loadShadersObject() if (success) { gObjectPreviewProgram.mName = "Simple Shader"; - gObjectPreviewProgram.mFeatures.calculatesLighting = true; - gObjectPreviewProgram.mFeatures.calculatesAtmospherics = true; - gObjectPreviewProgram.mFeatures.hasGamma = true; - gObjectPreviewProgram.mFeatures.hasAtmospherics = true; - gObjectPreviewProgram.mFeatures.hasLighting = true; + gObjectPreviewProgram.mFeatures.calculatesLighting = false; + gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasGamma = false; + gObjectPreviewProgram.mFeatures.hasAtmospherics = false; + gObjectPreviewProgram.mFeatures.hasLighting = false; gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; gObjectPreviewProgram.mFeatures.disableTextureIndex = true; gObjectPreviewProgram.mShaderFiles.clear(); gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); - gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/simpleF.glsl", GL_FRAGMENT_SHADER_ARB)); + gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewF.glsl", GL_FRAGMENT_SHADER_ARB)); gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT]; success = gObjectPreviewProgram.createShader(NULL, NULL); + gObjectPreviewProgram.mFeatures.hasLighting = true; } if (success) From b901e57c55344291ca751251084ab3f8c5e6d017 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 15:00:50 -0600 Subject: [PATCH 07/18] Start culling of llmemtype (for now just #ifdef'd to nothingness. --- indra/llcommon/llallocator.cpp | 33 --------------------------------- indra/llcommon/llallocator.h | 6 ------ indra/llcommon/llmemtype.cpp | 5 ++++- indra/llcommon/llmemtype.h | 11 +++++++++++ 4 files changed, 15 insertions(+), 40 deletions(-) diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp index 87654b5b9..34fc28d8c 100644 --- a/indra/llcommon/llallocator.cpp +++ b/indra/llcommon/llallocator.cpp @@ -35,28 +35,6 @@ DECLARE_bool(heap_profile_use_stack_trace); //DECLARE_double(tcmalloc_release_rate); -// static -void LLAllocator::pushMemType(S32 type) -{ - if(isProfiling()) - { - PushMemType(type); - } -} - -// static -S32 LLAllocator::popMemType() -{ - if (isProfiling()) - { - return PopMemType(); - } - else - { - return -1; - } -} - void LLAllocator::setProfilingEnabled(bool should_enable) { // NULL disables dumping to disk @@ -94,17 +72,6 @@ std::string LLAllocator::getRawProfile() // stub implementations for when tcmalloc is disabled // -// static -void LLAllocator::pushMemType(S32 type) -{ -} - -// static -S32 LLAllocator::popMemType() -{ - return -1; -} - void LLAllocator::setProfilingEnabled(bool should_enable) { } diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h index a91dd57d1..d26ad73c5 100644 --- a/indra/llcommon/llallocator.h +++ b/indra/llcommon/llallocator.h @@ -29,16 +29,10 @@ #include -#include "llmemtype.h" #include "llallocator_heap_profile.h" class LL_COMMON_API LLAllocator { friend class LLMemoryView; - friend class LLMemType; - -private: - static void pushMemType(S32 type); - static S32 popMemType(); public: void setProfilingEnabled(bool should_enable); diff --git a/indra/llcommon/llmemtype.cpp b/indra/llcommon/llmemtype.cpp index 9dcdaeff1..614dee323 100644 --- a/indra/llcommon/llmemtype.cpp +++ b/indra/llcommon/llmemtype.cpp @@ -27,7 +27,9 @@ #include "llmemtype.h" #include "llallocator.h" +#if MEM_TRACK_TYPE std::vector LLMemType::DeclareMemType::mNameList; +#endif LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init"); LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup"); @@ -194,7 +196,7 @@ LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9"); LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other"); - +#if MEM_TRACK_TYPE LLMemType::DeclareMemType::DeclareMemType(char const * st) { mID = (S32)mNameList.size(); @@ -229,3 +231,4 @@ char const * LLMemType::getNameFromID(S32 id) } //-------------------------------------------------------------------------------------------------- +#endif //MEM_TRACK_TYPE \ No newline at end of file diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index b51d7e0f6..2a411eb90 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -52,6 +52,10 @@ public: class LL_COMMON_API DeclareMemType { public: + +#if !MEM_TRACK_TYPE + DeclareMemType(char const * st) {}; //Do nothing +#else DeclareMemType(char const * st); ~DeclareMemType(); @@ -60,12 +64,17 @@ public: // array so we can map an index ID to Name static std::vector mNameList; +#endif }; +#if !MEM_TRACK_TYPE + LLMemType(DeclareMemType& dt){} //Do nothing +#else LLMemType(DeclareMemType& dt); ~LLMemType(); static char const * getNameFromID(S32 id); +#endif static DeclareMemType MTYPE_INIT; static DeclareMemType MTYPE_STARTUP; @@ -232,7 +241,9 @@ public: static DeclareMemType MTYPE_OTHER; // Special; used by display code +#if MEM_TRACK_TYPE S32 mTypeIndex; +#endif }; //---------------------------------------------------------------------------- From 1eb142535c1a5734c3c857e60aaf4c8a53902cac Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 15:02:17 -0600 Subject: [PATCH 08/18] Merge in changes to avoid a few potential problems with LLUUID when accessed from multiple threads. --- indra/llcommon/lluuid.cpp | 36 +++++++++++++++++++++++++++--------- indra/llcommon/lluuid.h | 3 +++ 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/indra/llcommon/lluuid.cpp b/indra/llcommon/lluuid.cpp index 1cbd888e5..f6b9db6c1 100644 --- a/indra/llcommon/lluuid.cpp +++ b/indra/llcommon/lluuid.cpp @@ -41,10 +41,15 @@ #include "llmd5.h" #include "llstring.h" #include "lltimer.h" +#include "llthread.h" const LLUUID LLUUID::null; const LLTransactionID LLTransactionID::tnull; +// static +LLMutex * LLUUID::mMutex = NULL; + + /* NOT DONE YET!!! @@ -731,6 +736,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp) getSystemTime(&time_last); uuids_this_tick = uuids_per_tick; init = TRUE; + mMutex = new LLMutex; } uuid_time_t time_now = {0,0}; @@ -782,6 +788,7 @@ void LLUUID::generate() #endif if (!has_init) { + has_init = 1; if (getNodeID(node_id) <= 0) { get_random_bytes(node_id, 6); @@ -803,18 +810,24 @@ void LLUUID::generate() #else clock_seq = (U16)ll_rand(65536); #endif - has_init = 1; } // get current time getCurrentTime(×tamp); + U16 our_clock_seq = clock_seq; - // if clock went backward change clockseq - if (cmpTime(×tamp, &time_last) == -1) { + // if clock hasn't changed or went backward, change clockseq + if (cmpTime(×tamp, &time_last) != 1) + { + LLMutexLock lock(mMutex); clock_seq = (clock_seq + 1) & 0x3FFF; - if (clock_seq == 0) clock_seq++; + if (clock_seq == 0) + clock_seq++; + our_clock_seq = clock_seq; // Ensure we're using a different clock_seq value from previous time } + time_last = timestamp; + memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */ U32 tmp; tmp = timestamp.low; @@ -836,7 +849,8 @@ void LLUUID::generate() tmp >>= 8; mData[6] = (unsigned char) tmp; - tmp = clock_seq; + tmp = our_clock_seq; + mData[9] = (unsigned char) tmp; tmp >>= 8; mData[8] = (unsigned char) tmp; @@ -846,8 +860,6 @@ void LLUUID::generate() md5_uuid.update(mData,16); md5_uuid.finalize(); md5_uuid.raw_digest(mData); - - time_last = timestamp; } void LLUUID::generate(const std::string& hash_string) @@ -861,8 +873,14 @@ U32 LLUUID::getRandomSeed() static unsigned char seed[16]; /* Flawfinder: ignore */ getNodeID(&seed[0]); - seed[6]='\0'; - seed[7]='\0'; + + // Incorporate the pid into the seed to prevent + // processes that start on the same host at the same + // time from generating the same seed. + pid_t pid = LLApp::getPid(); + + seed[6]=(unsigned char)(pid >> 8); + seed[7]=(unsigned char)(pid); getSystemTime((uuid_time_t *)(&seed[8])); LLMD5 md5_seed; diff --git a/indra/llcommon/lluuid.h b/indra/llcommon/lluuid.h index 726be4a82..4e5bed189 100644 --- a/indra/llcommon/lluuid.h +++ b/indra/llcommon/lluuid.h @@ -31,6 +31,8 @@ #include "stdtypes.h" #include "llpreprocessor.h" +class LLMutex; + const S32 UUID_BYTES = 16; const S32 UUID_WORDS = 4; const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below @@ -118,6 +120,7 @@ public: static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal. static const LLUUID null; + static LLMutex * mMutex; static U32 getRandomSeed(); static S32 getNodeID(unsigned char * node_id); From c92c68dee2162fb11ea3dc9fbeca6db328811251 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 15:07:07 -0600 Subject: [PATCH 09/18] A few more preview-related changes. --- indra/newview/llfloaterimagepreview.cpp | 4 +++- indra/newview/pipeline.cpp | 25 +++++++++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/indra/newview/llfloaterimagepreview.cpp b/indra/newview/llfloaterimagepreview.cpp index 013c9aa49..72e46f09c 100644 --- a/indra/newview/llfloaterimagepreview.cpp +++ b/indra/newview/llfloaterimagepreview.cpp @@ -973,11 +973,13 @@ BOOL LLImagePreviewSculpted::render() { gObjectPreviewProgram.bind(); } + gPipeline.enableLightsPreview(); + gGL.pushMatrix(); const F32 SCALE = 1.25f; gGL.scalef(SCALE, SCALE, SCALE); const F32 BRIGHTNESS = 0.9f; - gGL.color3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); + gGL.diffuseColor3f(BRIGHTNESS, BRIGHTNESS, BRIGHTNESS); mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0); mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 88b9f9c20..fff60e992 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -489,7 +489,10 @@ void LLPipeline::init() //gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("UseOcclusion")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("VertexShaderEnable")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderDeferred")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); gSavedSettings.getControl("RenderFSAASamples")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("RenderAvatarVP")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); + gSavedSettings.getControl("WindLightUseAtmosShaders")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); } LLPipeline::~LLPipeline() @@ -631,7 +634,16 @@ void LLPipeline::resizeScreenTexture() GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resY = gViewerWindow->getWorldViewHeightRaw(); - allocateScreenBuffer(resX,resY); + if (!allocateScreenBuffer(resX,resY)) + { //FAILSAFE: screen buffer allocation failed, disable deferred rendering if it's enabled + //NOTE: if the session closes successfully after this call, deferred rendering will be + // disabled on future sessions + if (LLPipeline::sRenderDeferred) + { + gSavedSettings.setBOOL("RenderDeferred", FALSE); + LLPipeline::refreshCachedSettings(); + } + } } } @@ -902,6 +914,8 @@ void LLPipeline::refreshCachedSettings() && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) ? 2 : 0; + + updateRenderDeferred(); } void LLPipeline::releaseGLBuffers() @@ -5412,7 +5426,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) if (light->isLightSpotlight() // directional (spot-)light && (LLPipeline::sRenderDeferred || RenderSpotLightsInNondeferred)) // these are only rendered as GL spotlights if we're in deferred rendering mode *or* the setting forces them on { - LLVector3 spotparams = light->getSpotLightParams(); LLQuaternion quat = light->getRenderRotation(); LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction at_axis *= quat; @@ -5460,7 +5473,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) F32 light_radius = 16.f; - F32 x = 3.f; + F32 x = 3.f; float linatten = x / (light_radius); // % of brightness at radius mHWLightColors[2] = light_color; @@ -5624,7 +5637,7 @@ void LLPipeline::enableLightsPreview() LLVector4 light_pos(dir0, 0.0f); - LLLightState* light = gGL.getLight(0); + LLLightState* light = gGL.getLight(1); light->enable(); light->setPosition(light_pos); @@ -5636,7 +5649,7 @@ void LLPipeline::enableLightsPreview() light_pos = LLVector4(dir1, 0.f); - light = gGL.getLight(1); + light = gGL.getLight(2); light->enable(); light->setPosition(light_pos); light->setDiffuse(diffuse1); @@ -5646,7 +5659,7 @@ void LLPipeline::enableLightsPreview() light->setSpotCutoff(180.f); light_pos = LLVector4(dir2, 0.f); - light = gGL.getLight(2); + light = gGL.getLight(3); light->enable(); light->setPosition(light_pos); light->setDiffuse(diffuse2); From 24efffc68a61341d00242b414e3bfd185494e107 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 15:08:11 -0600 Subject: [PATCH 10/18] LLInitParam merge. --- indra/llcommon/llinitparam.h | 204 ++++++++++++++++++++--------------- 1 file changed, 119 insertions(+), 85 deletions(-) diff --git a/indra/llcommon/llinitparam.h b/indra/llcommon/llinitparam.h index 993f16d04..b79417f96 100644 --- a/indra/llcommon/llinitparam.h +++ b/indra/llcommon/llinitparam.h @@ -31,6 +31,7 @@ #include #include #include +#include #include #include @@ -224,32 +225,81 @@ namespace LLInitParam typedef std::map parser_write_func_map_t; typedef std::map parser_inspect_func_map_t; + private: + template::value> + struct ReaderWriter + { + static bool read(T& param, Parser* parser) + { + parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(T)); + if (found_it != parser->mParserReadFuncs->end()) + { + return found_it->second(*parser, (void*)¶m); + } + return false; + } + + static bool write(const T& param, Parser* parser, name_stack_t& name_stack) + { + parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(T)); + if (found_it != parser->mParserWriteFuncs->end()) + { + return found_it->second(*parser, (const void*)¶m, name_stack); + } + return false; + } + }; + + // read enums as ints + template + struct ReaderWriter + { + static bool read(T& param, Parser* parser) + { + // read all enums as ints + parser_read_func_map_t::iterator found_it = parser->mParserReadFuncs->find(&typeid(S32)); + if (found_it != parser->mParserReadFuncs->end()) + { + S32 value; + if (found_it->second(*parser, (void*)&value)) + { + param = (T)value; + return true; + } + } + return false; + } + + static bool write(const T& param, Parser* parser, name_stack_t& name_stack) + { + parser_write_func_map_t::iterator found_it = parser->mParserWriteFuncs->find(&typeid(S32)); + if (found_it != parser->mParserWriteFuncs->end()) + { + return found_it->second(*parser, (const void*)¶m, name_stack); + } + return false; + } + }; + + public: + Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map) : mParseSilently(false), mParserReadFuncs(&read_map), mParserWriteFuncs(&write_map), mParserInspectFuncs(&inspect_map) {} + virtual ~Parser(); template bool readValue(T& param) { - parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); - if (found_it != mParserReadFuncs->end()) - { - return found_it->second(*this, (void*)¶m); - } - return false; + return ReaderWriter::read(param, this); } template bool writeValue(const T& param, name_stack_t& name_stack) { - parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); - if (found_it != mParserWriteFuncs->end()) - { - return found_it->second(*this, (const void*)¶m, name_stack); - } - return false; + return ReaderWriter::write(param, this, name_stack); } // dispatch inspection to registered inspection functions, for each parameter in a param block @@ -841,31 +891,25 @@ namespace LLInitParam self_t& typed_param = static_cast(param); // no further names in stack, attempt to parse value now if (name_stack_range.first == name_stack_range.second) - { - if (parser.readValue(typed_param.getValue())) + { + std::string name; + + // try to parse a known named value + if(name_value_lookup_t::valueNamesExist() + && parser.readValue(name) + && name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + { + typed_param.setValueName(name); + typed_param.setProvided(); + return true; + } + // try to read value directly + else if (parser.readValue(typed_param.getValue())) { typed_param.clearValueName(); typed_param.setProvided(); return true; } - - // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) - { - typed_param.setValueName(name); - typed_param.setProvided(); - return true; - } - - } - } } return false; } @@ -987,30 +1031,29 @@ namespace LLInitParam static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack_range, bool new_name) { self_t& typed_param = static_cast(param); - // attempt to parse block... + + if (name_stack_range.first == name_stack_range.second) + { // try to parse a known named value + std::string name; + + if(name_value_lookup_t::valueNamesExist() + && parser.readValue(name) + && name_value_lookup_t::getValueFromName(name, typed_param.getValue())) + { + typed_param.setValueName(name); + typed_param.setProvided(); + return true; + } + } + if(typed_param.deserializeBlock(parser, name_stack_range, new_name)) - { + { // attempt to parse block... typed_param.clearValueName(); typed_param.setProvided(); return true; } - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, typed_param.getValue())) - { - typed_param.setValueName(name); - typed_param.setProvided(); - return true; - } - } - } return false; } @@ -1160,31 +1203,23 @@ namespace LLInitParam value_t value; // no further names in stack, attempt to parse value now if (name_stack_range.first == name_stack_range.second) - { - // attempt to read value directly - if (parser.readValue(value)) + { + std::string name; + + // try to parse a known named value + if(name_value_lookup_t::valueNamesExist() + && parser.readValue(name) + && name_value_lookup_t::getValueFromName(name, value)) + { + typed_param.add(value); + typed_param.mValues.back().setValueName(name); + return true; + } + else if (parser.readValue(value)) // attempt to read value directly { typed_param.add(value); return true; } - - // try to parse a known named value - if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value)) - { - typed_param.add(value); - typed_param.mValues.back().setValueName(name); - return true; - } - - } - } } return false; } @@ -1362,28 +1397,27 @@ namespace LLInitParam param_value_t& value = typed_param.mValues.back(); + if (name_stack_range.first == name_stack_range.second) + { // try to parse a known named value + std::string name; + + if(name_value_lookup_t::valueNamesExist() + && parser.readValue(name) + && name_value_lookup_t::getValueFromName(name, value.getValue())) + { + typed_param.mValues.back().setValueName(name); + typed_param.setProvided(); + return true; + } + } + // attempt to parse block... if(value.deserializeBlock(parser, name_stack_range, new_name)) { typed_param.setProvided(); return true; } - else if(name_value_lookup_t::valueNamesExist()) - { - // try to parse a known named value - std::string name; - if (parser.readValue(name)) - { - // try to parse a per type named value - if (name_value_lookup_t::getValueFromName(name, value.getValue())) - { - typed_param.mValues.back().setValueName(name); - typed_param.setProvided(); - return true; - } - } - } if (new_value) { // failed to parse new value, pop it off From 6725c17f0184d10ee71ac3c1c180d7cfa5686288 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 15:10:15 -0600 Subject: [PATCH 11/18] LLSys merge and cleanup. --- indra/llcommon/llsys.cpp | 625 ++++++++++++++++++++++++++++++++++++--- indra/llcommon/llsys.h | 21 ++ 2 files changed, 603 insertions(+), 43 deletions(-) diff --git a/indra/llcommon/llsys.cpp b/indra/llcommon/llsys.cpp index 4056b3253..c96f2191f 100644 --- a/indra/llcommon/llsys.cpp +++ b/indra/llcommon/llsys.cpp @@ -24,6 +24,10 @@ * $/LicenseInfo$ */ +#if LL_WINDOWS +#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally +#endif + #include "linden_common.h" #include "llsys.h" @@ -36,22 +40,45 @@ #endif #include "llprocessor.h" +#include "llerrorcontrol.h" +#include "llevents.h" +#include "lltimer.h" +#include "llsdserialize.h" +#include "llsdutil.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace llsd; #if LL_WINDOWS # define WIN32_LEAN_AND_MEAN # include # include +# include // GetPerformanceInfo() et al. #elif LL_DARWIN # include # include # include # include # include +# include +# include +# include +# include +# include #elif LL_LINUX # include # include # include # include +# include const char MEMINFO_FILE[] = "/proc/meminfo"; #elif LL_SOLARIS # include @@ -70,6 +97,15 @@ extern int errno; static const S32 CPUINFO_BUFFER_SIZE = 16383; LLCPUInfo gSysCPU; +// Don't log memory info any more often than this. It also serves as our +// framerate sample size. +static const F32 MEM_INFO_THROTTLE = 20; +// Sliding window of samples. We intentionally limit the length of time we +// remember "the slowest" framerate because framerate is very slow at login. +// If we only triggered FrameWatcher logging when the session framerate +// dropped below the login framerate, we'd have very little additional data. +static const F32 MEM_INFO_WINDOW = 10*60; + #if LL_WINDOWS #ifndef DLLVERSIONINFO typedef struct _DllVersionInfo @@ -572,6 +608,7 @@ LLCPUInfo::LLCPUInfo() out << " (" << mCPUMHz << " MHz)"; } mCPUString = out.str(); + LLStringUtil::trim(mCPUString); } bool LLCPUInfo::hasAltivec() const @@ -613,8 +650,78 @@ void LLCPUInfo::stream(std::ostream& s) const s << "->mCPUString: " << mCPUString << std::endl; } +// Helper class for LLMemoryInfo: accumulate stats in the form we store for +// LLMemoryInfo::getStatsMap(). +class Stats +{ +public: + Stats(): + mStats(LLSD::emptyMap()) + {} + + // Store every integer type as LLSD::Integer. + template + void add(const LLSD::String& name, const T& value, + typename boost::enable_if >::type* = 0) + { + mStats[name] = LLSD::Integer(value); + } + + // Store every floating-point type as LLSD::Real. + template + void add(const LLSD::String& name, const T& value, + typename boost::enable_if >::type* = 0) + { + mStats[name] = LLSD::Real(value); + } + + // Hope that LLSD::Date values are sufficiently unambiguous. + void add(const LLSD::String& name, const LLSD::Date& value) + { + mStats[name] = value; + } + + LLSD get() const { return mStats; } + +private: + LLSD mStats; +}; + +// Wrap boost::regex_match() with a function that doesn't throw. +template +static bool regex_match_no_exc(const S& string, M& match, const R& regex) +{ + try + { + return boost::regex_match(string, match, regex); + } + catch (const std::runtime_error& e) + { + LL_WARNS("LLMemoryInfo") << "error matching with '" << regex.str() << "': " + << e.what() << ":\n'" << string << "'" << LL_ENDL; + return false; + } +} + +// Wrap boost::regex_search() with a function that doesn't throw. +template +static bool regex_search_no_exc(const S& string, M& match, const R& regex) +{ + try + { + return boost::regex_search(string, match, regex); + } + catch (const std::runtime_error& e) + { + LL_WARNS("LLMemoryInfo") << "error searching with '" << regex.str() << "': " + << e.what() << ":\n'" << string << "'" << LL_ENDL; + return false; + } +} + LLMemoryInfo::LLMemoryInfo() { + refresh(); } #if LL_WINDOWS @@ -638,11 +745,7 @@ static U32 LLMemoryAdjustKBResult(U32 inKB) U32 LLMemoryInfo::getPhysicalMemoryKB() const { #if LL_WINDOWS - MEMORYSTATUSEX state; - state.dwLength = sizeof(state); - GlobalMemoryStatusEx(&state); - - return LLMemoryAdjustKBResult((U32)(state.ullTotalPhys >> 10)); + return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger()); #elif LL_DARWIN // This might work on Linux as well. Someone check... @@ -690,12 +793,82 @@ U32 LLMemoryInfo::getPhysicalMemoryClamped() const void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb) { #if LL_WINDOWS - MEMORYSTATUSEX state; - state.dwLength = sizeof(state); - GlobalMemoryStatusEx(&state); + // Sigh, this shouldn't be a static method, then we wouldn't have to + // reload this data separately from refresh() + LLSD statsMap(loadStatsMap()); - avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ; - avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ; + avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger(); + avail_virtual_mem_kb = statsMap["Avail Virtual KB"].asInteger(); + +#elif LL_DARWIN + // mStatsMap is derived from vm_stat, look for (e.g.) "kb free": + // $ vm_stat + // Mach Virtual Memory Statistics: (page size of 4096 bytes) + // Pages free: 462078. + // Pages active: 142010. + // Pages inactive: 220007. + // Pages wired down: 159552. + // "Translation faults": 220825184. + // Pages copy-on-write: 2104153. + // Pages zero filled: 167034876. + // Pages reactivated: 65153. + // Pageins: 2097212. + // Pageouts: 41759. + // Object cache: 841598 hits of 7629869 lookups (11% hit rate) + avail_physical_mem_kb = -1 ; + avail_virtual_mem_kb = -1 ; + +#elif LL_LINUX + // mStatsMap is derived from MEMINFO_FILE: + // $ cat /proc/meminfo + // MemTotal: 4108424 kB + // MemFree: 1244064 kB + // Buffers: 85164 kB + // Cached: 1990264 kB + // SwapCached: 0 kB + // Active: 1176648 kB + // Inactive: 1427532 kB + // Active(anon): 529152 kB + // Inactive(anon): 15924 kB + // Active(file): 647496 kB + // Inactive(file): 1411608 kB + // Unevictable: 16 kB + // Mlocked: 16 kB + // HighTotal: 3266316 kB + // HighFree: 721308 kB + // LowTotal: 842108 kB + // LowFree: 522756 kB + // SwapTotal: 6384632 kB + // SwapFree: 6384632 kB + // Dirty: 28 kB + // Writeback: 0 kB + // AnonPages: 528820 kB + // Mapped: 89472 kB + // Shmem: 16324 kB + // Slab: 159624 kB + // SReclaimable: 145168 kB + // SUnreclaim: 14456 kB + // KernelStack: 2560 kB + // PageTables: 5560 kB + // NFS_Unstable: 0 kB + // Bounce: 0 kB + // WritebackTmp: 0 kB + // CommitLimit: 8438844 kB + // Committed_AS: 1271596 kB + // VmallocTotal: 122880 kB + // VmallocUsed: 65252 kB + // VmallocChunk: 52356 kB + // HardwareCorrupted: 0 kB + // HugePages_Total: 0 + // HugePages_Free: 0 + // HugePages_Rsvd: 0 + // HugePages_Surp: 0 + // Hugepagesize: 2048 kB + // DirectMap4k: 434168 kB + // DirectMap2M: 477184 kB + // (could also run 'free', but easier to read a file than run a program) + avail_physical_mem_kb = -1 ; + avail_virtual_mem_kb = -1 ; #else //do not know how to collect available memory info for other systems. @@ -708,56 +881,285 @@ void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_v void LLMemoryInfo::stream(std::ostream& s) const { + // We want these memory stats to be easy to grep from the log, along with + // the timestamp. So preface each line with the timestamp and a + // distinctive marker. Without that, we'd have to search the log for the + // introducer line, then read subsequent lines, etc... + std::string pfx(LLError::utcTime() + " "); + + // Max key length + size_t key_width(0); + BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap)) + { + size_t len(pair.first.length()); + if (len > key_width) + { + key_width = len; + } + } + + // Now stream stats + BOOST_FOREACH(const MapEntry& pair, inMap(mStatsMap)) + { + s << pfx << std::setw(key_width+1) << (pair.first + ':') << ' '; + LLSD value(pair.second); + if (value.isInteger()) + s << std::setw(12) << value.asInteger(); + else if (value.isReal()) + s << std::fixed << std::setprecision(1) << value.asReal(); + else if (value.isDate()) + value.asDate().toStream(s); + else + s << value; // just use default LLSD formatting + s << std::endl; + } +} + +LLSD LLMemoryInfo::getStatsMap() const +{ + return mStatsMap; +} + +LLMemoryInfo& LLMemoryInfo::refresh() +{ + mStatsMap = loadStatsMap(); + + LL_DEBUGS("LLMemoryInfo") << "Populated mStatsMap:\n"; + LLSDSerialize::toPrettyXML(mStatsMap, LL_CONT); + LL_ENDL; + + return *this; +} + +LLSD LLMemoryInfo::loadStatsMap() +{ + // This implementation is derived from stream() code (as of 2011-06-29). + Stats stats; + + // associate timestamp for analysis over time + stats.add("timestamp", LLDate::now()); + #if LL_WINDOWS MEMORYSTATUSEX state; state.dwLength = sizeof(state); GlobalMemoryStatusEx(&state); - s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl; - s << "Total Physical KB: " << (U32)(state.ullTotalPhys/1024) << std::endl; - s << "Avail Physical KB: " << (U32)(state.ullAvailPhys/1024) << std::endl; - s << "Total page KB: " << (U32)(state.ullTotalPageFile/1024) << std::endl; - s << "Avail page KB: " << (U32)(state.ullAvailPageFile/1024) << std::endl; - s << "Total Virtual KB: " << (U32)(state.ullTotalVirtual/1024) << std::endl; - s << "Avail Virtual KB: " << (U32)(state.ullAvailVirtual/1024) << std::endl; + DWORDLONG div = 1024; + + stats.add("Percent Memory use", state.dwMemoryLoad/div); + stats.add("Total Physical KB", state.ullTotalPhys/div); + stats.add("Avail Physical KB", state.ullAvailPhys/div); + stats.add("Total page KB", state.ullTotalPageFile/div); + stats.add("Avail page KB", state.ullAvailPageFile/div); + stats.add("Total Virtual KB", state.ullTotalVirtual/div); + stats.add("Avail Virtual KB", state.ullAvailVirtual/div); + + PERFORMANCE_INFORMATION perf; + perf.cb = sizeof(perf); + GetPerformanceInfo(&perf, sizeof(perf)); + + SIZE_T pagekb(perf.PageSize/1024); + stats.add("CommitTotal KB", perf.CommitTotal * pagekb); + stats.add("CommitLimit KB", perf.CommitLimit * pagekb); + stats.add("CommitPeak KB", perf.CommitPeak * pagekb); + stats.add("PhysicalTotal KB", perf.PhysicalTotal * pagekb); + stats.add("PhysicalAvail KB", perf.PhysicalAvailable * pagekb); + stats.add("SystemCache KB", perf.SystemCache * pagekb); + stats.add("KernelTotal KB", perf.KernelTotal * pagekb); + stats.add("KernelPaged KB", perf.KernelPaged * pagekb); + stats.add("KernelNonpaged KB", perf.KernelNonpaged * pagekb); + stats.add("PageSize KB", pagekb); + stats.add("HandleCount", perf.HandleCount); + stats.add("ProcessCount", perf.ProcessCount); + stats.add("ThreadCount", perf.ThreadCount); + + PROCESS_MEMORY_COUNTERS_EX pmem; + pmem.cb = sizeof(pmem); + // GetProcessMemoryInfo() is documented to accept either + // PROCESS_MEMORY_COUNTERS* or PROCESS_MEMORY_COUNTERS_EX*, presumably + // using the redundant size info to distinguish. But its prototype + // specifically accepts PROCESS_MEMORY_COUNTERS*, and since this is a + // classic-C API, PROCESS_MEMORY_COUNTERS_EX isn't a subclass. Cast the + // pointer. + GetProcessMemoryInfo(GetCurrentProcess(), PPROCESS_MEMORY_COUNTERS(&pmem), sizeof(pmem)); + + stats.add("Page Fault Count", pmem.PageFaultCount); + stats.add("PeakWorkingSetSize KB", pmem.PeakWorkingSetSize/div); + stats.add("WorkingSetSize KB", pmem.WorkingSetSize/div); + stats.add("QutaPeakPagedPoolUsage KB", pmem.QuotaPeakPagedPoolUsage/div); + stats.add("QuotaPagedPoolUsage KB", pmem.QuotaPagedPoolUsage/div); + stats.add("QuotaPeakNonPagedPoolUsage KB", pmem.QuotaPeakNonPagedPoolUsage/div); + stats.add("QuotaNonPagedPoolUsage KB", pmem.QuotaNonPagedPoolUsage/div); + stats.add("PagefileUsage KB", pmem.PagefileUsage/div); + stats.add("PeakPagefileUsage KB", pmem.PeakPagefileUsage/div); + stats.add("PrivateUsage KB", pmem.PrivateUsage/div); + #elif LL_DARWIN - uint64_t phys = 0; - size_t len = sizeof(phys); + const vm_size_t pagekb(vm_page_size / 1024); + + // + // Collect the vm_stat's + // - if(sysctlbyname("hw.memsize", &phys, &len, NULL, 0) == 0) { - s << "Total Physical KB: " << phys/1024 << std::endl; - } - else - { - s << "Unable to collect memory information"; - } -#elif LL_SOLARIS - U64 phys = 0; + vm_statistics_data_t vmstat; + mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT; - phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024); - - s << "Total Physical KB: " << phys << std::endl; -#else - // *NOTE: This works on linux. What will it do on other systems? - LLFILE* meminfo = LLFile::fopen(MEMINFO_FILE,"rb"); - if(meminfo) + if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS) { - char line[MAX_STRING]; /* Flawfinder: ignore */ - memset(line, 0, MAX_STRING); - while(fgets(line, MAX_STRING, meminfo)) - { - line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/ - s << line; + LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL; + } + else + { + stats.add("Pages free KB", pagekb * vmstat.free_count); + stats.add("Pages active KB", pagekb * vmstat.active_count); + stats.add("Pages inactive KB", pagekb * vmstat.inactive_count); + stats.add("Pages wired KB", pagekb * vmstat.wire_count); + + stats.add("Pages zero fill", vmstat.zero_fill_count); + stats.add("Page reactivations", vmstat.reactivations); + stats.add("Page-ins", vmstat.pageins); + stats.add("Page-outs", vmstat.pageouts); + + stats.add("Faults", vmstat.faults); + stats.add("Faults copy-on-write", vmstat.cow_faults); + + stats.add("Cache lookups", vmstat.lookups); + stats.add("Cache hits", vmstat.hits); + + stats.add("Page purgeable count", vmstat.purgeable_count); + stats.add("Page purges", vmstat.purges); + + stats.add("Page speculative reads", vmstat.speculative_count); + } + } + + // + // Collect the misc task info + // + + { + task_events_info_data_t taskinfo; + unsigned taskinfoSize = sizeof(taskinfo); + + if (task_info(mach_task_self(), TASK_EVENTS_INFO, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS) + { + LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL; + } + else + { + stats.add("Task page-ins", taskinfo.pageins); + stats.add("Task copy-on-write faults", taskinfo.cow_faults); + stats.add("Task messages sent", taskinfo.messages_sent); + stats.add("Task messages received", taskinfo.messages_received); + stats.add("Task mach system call count", taskinfo.syscalls_mach); + stats.add("Task unix system call count", taskinfo.syscalls_unix); + stats.add("Task context switch count", taskinfo.csw); + } + } + + // + // Collect the basic task info + // + + { + task_basic_info_64_data_t taskinfo; + unsigned taskinfoSize = sizeof(taskinfo); + + if (task_info(mach_task_self(), TASK_BASIC_INFO_64, (task_info_t) &taskinfo, &taskinfoSize) != KERN_SUCCESS) + { + LL_WARNS("LLMemoryInfo") << "Unable to collect task information" << LL_ENDL; + } + else + { + stats.add("Basic suspend count", taskinfo.suspend_count); + stats.add("Basic virtual memory KB", taskinfo.virtual_size / 1024); + stats.add("Basic resident memory KB", taskinfo.resident_size / 1024); + stats.add("Basic new thread policy", taskinfo.policy); + } + } + +#elif LL_SOLARIS + U64 phys = 0; + + phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024); + + stats.add("Total Physical KB", phys); + +#elif LL_LINUX + std::ifstream meminfo(MEMINFO_FILE); + if (meminfo.is_open()) + { + // MemTotal: 4108424 kB + // MemFree: 1244064 kB + // Buffers: 85164 kB + // Cached: 1990264 kB + // SwapCached: 0 kB + // Active: 1176648 kB + // Inactive: 1427532 kB + // ... + // VmallocTotal: 122880 kB + // VmallocUsed: 65252 kB + // VmallocChunk: 52356 kB + // HardwareCorrupted: 0 kB + // HugePages_Total: 0 + // HugePages_Free: 0 + // HugePages_Rsvd: 0 + // HugePages_Surp: 0 + // Hugepagesize: 2048 kB + // DirectMap4k: 434168 kB + // DirectMap2M: 477184 kB + + // Intentionally don't pass the boost::no_except flag. This + // boost::regex object is constructed with a string literal, so it + // should be valid every time. If it becomes invalid, we WANT an + // exception, hopefully even before the dev checks in. + boost::regex stat_rx("(.+): +([0-9]+)( kB)?"); + boost::smatch matched; + + std::string line; + while (std::getline(meminfo, line)) + { + LL_DEBUGS("LLMemoryInfo") << line << LL_ENDL; + if (regex_match_no_exc(line, matched, stat_rx)) + { + // e.g. "MemTotal: 4108424 kB" + LLSD::String key(matched[1].first, matched[1].second); + LLSD::String value_str(matched[2].first, matched[2].second); + LLSD::Integer value(0); + try + { + value = boost::lexical_cast(value_str); + } + catch (const boost::bad_lexical_cast&) + { + LL_WARNS("LLMemoryInfo") << "couldn't parse '" << value_str + << "' in " << MEMINFO_FILE << " line: " + << line << LL_ENDL; + continue; + } + // Store this statistic. + stats.add(key, value); + } + else + { + LL_WARNS("LLMemoryInfo") << "unrecognized " << MEMINFO_FILE << " line: " + << line << LL_ENDL; + } } - fclose(meminfo); } else { - s << "Unable to collect memory information"; + LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL; } + +#else + LL_WARNS("LLMemoryInfo") << "Unknown system; unable to collect memory information" << LL_ENDL; + #endif + + return stats.get(); } std::ostream& operator<<(std::ostream& s, const LLOSInfo& info) @@ -778,6 +1180,143 @@ std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info) return s; } +class FrameWatcher +{ +public: + FrameWatcher(): + // Hooking onto the "mainloop" event pump gets us one call per frame. + mConnection(LLEventPumps::instance() + .obtain("mainloop") + .listen("FrameWatcher", boost::bind(&FrameWatcher::tick, this, _1))), + // Initializing mSampleStart to an invalid timestamp alerts us to skip + // trying to compute framerate on the first call. + mSampleStart(-1), + // Initializing mSampleEnd to 0 ensures that we treat the first call + // as the completion of a sample window. + mSampleEnd(0), + mFrames(0), + // Both MEM_INFO_WINDOW and MEM_INFO_THROTTLE are in seconds. We need + // the number of integer MEM_INFO_THROTTLE sample slots that will fit + // in MEM_INFO_WINDOW. Round up. + mSamples(int((MEM_INFO_WINDOW / MEM_INFO_THROTTLE) + 0.7)), + // Initializing to F32_MAX means that the first real frame will become + // the slowest ever, which sounds like a good idea. + mSlowest(F32_MAX) + {} + + bool tick(const LLSD&) + { + F32 timestamp(mTimer.getElapsedTimeF32()); + + // Count this frame in the interval just completed. + ++mFrames; + + // Have we finished a sample window yet? + if (timestamp < mSampleEnd) + { + // no, just keep waiting + return false; + } + + // Set up for next sample window. Capture values for previous frame in + // local variables and reset data members. + U32 frames(mFrames); + F32 sampleStart(mSampleStart); + // No frames yet in next window + mFrames = 0; + // which starts right now + mSampleStart = timestamp; + // and ends MEM_INFO_THROTTLE seconds in the future + mSampleEnd = mSampleStart + MEM_INFO_THROTTLE; + + // On the very first call, that's all we can do, no framerate + // computation is possible. + if (sampleStart < 0) + { + return false; + } + + // How long did this actually take? As framerate slows, the duration + // of the frame we just finished could push us WELL beyond our desired + // sample window size. + F32 elapsed(timestamp - sampleStart); + F32 framerate(frames/elapsed); + + // Remember previous slowest framerate because we're just about to + // update it. + F32 slowest(mSlowest); + // Remember previous number of samples. + boost::circular_buffer::size_type prevSize(mSamples.size()); + + // Capture new framerate in our samples buffer. Once the buffer is + // full (after MEM_INFO_WINDOW seconds), this will displace the oldest + // sample. ("So they all rolled over, and one fell out...") + mSamples.push_back(framerate); + + // Calculate the new minimum framerate. I know of no way to update a + // rolling minimum without ever rescanning the buffer. But since there + // are only a few tens of items in this buffer, rescanning it is + // probably cheaper (and certainly easier to reason about) than + // attempting to optimize away some of the scans. + mSlowest = framerate; // pick an arbitrary entry to start + for (boost::circular_buffer::const_iterator si(mSamples.begin()), send(mSamples.end()); + si != send; ++si) + { + if (*si < mSlowest) + { + mSlowest = *si; + } + } + + // We're especially interested in memory as framerate drops. Only log + // when framerate drops below the slowest framerate we remember. + // (Should always be true for the end of the very first sample + // window.) + if (framerate >= slowest) + { + return false; + } + // Congratulations, we've hit a new low. :-P + + LL_INFOS("FrameWatcher") << ' '; + if (! prevSize) + { + LL_CONT << "initial framerate "; + } + else + { + LL_CONT << "slowest framerate for last " << int(prevSize * MEM_INFO_THROTTLE) + << " seconds "; + } + LL_CONT << std::fixed << std::setprecision(1) << framerate << '\n' + << LLMemoryInfo() << LL_ENDL; + + return false; + } + +private: + // Storing the connection in an LLTempBoundListener ensures it will be + // disconnected when we're destroyed. + LLTempBoundListener mConnection; + // Track elapsed time + LLTimer mTimer; + // Some of what you see here is in fact redundant with functionality you + // can get from LLTimer. Unfortunately the LLTimer API is missing the + // feature we need: has at least the stated interval elapsed, and if so, + // exactly how long has passed? So we have to do it by hand, sigh. + // Time at start, end of sample window + F32 mSampleStart, mSampleEnd; + // Frames this sample window + U32 mFrames; + // Sliding window of framerate samples + boost::circular_buffer mSamples; + // Slowest framerate in mSamples + F32 mSlowest; +}; + +// Need an instance of FrameWatcher before it does any good +static FrameWatcher sFrameWatcher; + BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile) { std::string tmpfile; diff --git a/indra/llcommon/llsys.h b/indra/llcommon/llsys.h index 41a4f2500..fb39ef4da 100644 --- a/indra/llcommon/llsys.h +++ b/indra/llcommon/llsys.h @@ -117,6 +117,27 @@ public: //get the available memory infomation in KiloBytes. static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb); + + // Retrieve a map of memory statistics. The keys of the map are platform- + // dependent. The values are in kilobytes to try to avoid integer overflow. + LLSD getStatsMap() const; + + // Re-fetch memory data (as reported by stream() and getStatsMap()) from the + // system. Normally this is fetched at construction time. Return (*this) + // to permit usage of the form: + // @code + // LLMemoryInfo info; + // ... + // info.refresh().getStatsMap(); + // @endcode + LLMemoryInfo& refresh(); + +private: + // set mStatsMap + static LLSD loadStatsMap(); + + // Memory stats for getStatsMap(). + LLSD mStatsMap; }; From f147a734b15511d0f1fecbcfd61c063dfaf0e848 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 20:47:55 -0600 Subject: [PATCH 12/18] LLStat dead code removal --- indra/llcommon/llstat.cpp | 996 ++-------------------------- indra/llcommon/llstat.h | 283 +------- indra/llmessage/llcircuit.cpp | 2 - indra/llmessage/llcircuit.h | 4 - indra/llmessage/lliohttpserver.cpp | 13 +- indra/llmessage/llmessagetemplate.h | 1 - indra/llmessage/llpumpio.cpp | 3 +- indra/newview/llfloaterjoystick.cpp | 3 +- indra/newview/llmemoryview.cpp | 2 + 9 files changed, 112 insertions(+), 1195 deletions(-) diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index ac5bdcffb..6cc2246e2 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -37,736 +37,30 @@ // statics -S32 LLPerfBlock::sStatsFlags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS; // Control what is being recorded -LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects -std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step" - //------------------------------------------------------------------------ -// Live config file to trigger stats logging -static const char STATS_CONFIG_FILE_NAME[] = "/dev/shm/simperf/simperf_proc_config.llsd"; -static const F32 STATS_CONFIG_REFRESH_RATE = 5.0; // seconds - -class LLStatsConfigFile : public LLLiveFile -{ -public: - LLStatsConfigFile() - : LLLiveFile(filename(), STATS_CONFIG_REFRESH_RATE), - mChanged(false), mStatsp(NULL) { } - - static std::string filename(); - -protected: - /* virtual */ bool loadFile(); - -public: - void init(LLPerfStats* statsp); - static LLStatsConfigFile& instance(); - // return the singleton stats config file - - bool mChanged; - -protected: - LLPerfStats* mStatsp; -}; - -std::string LLStatsConfigFile::filename() -{ - return STATS_CONFIG_FILE_NAME; -} - -void LLStatsConfigFile::init(LLPerfStats* statsp) -{ - mStatsp = statsp; -} - -LLStatsConfigFile& LLStatsConfigFile::instance() -{ - static LLStatsConfigFile the_file; - return the_file; -} - - -/* virtual */ -// Load and parse the stats configuration file -bool LLStatsConfigFile::loadFile() -{ - if (!mStatsp) - { - llwarns << "Tries to load performance configure file without initializing LPerfStats" << llendl; - return false; - } - mChanged = true; - - LLSD stats_config; - { - llifstream file(filename().c_str()); - if (file.is_open()) - { - LLSDSerialize::fromXML(stats_config, file); - if (stats_config.isUndefined()) - { - llinfos << "Performance statistics configuration file ill-formed, not recording statistics" << llendl; - mStatsp->setReportPerformanceDuration( 0.f ); - return false; - } - } - else - { // File went away, turn off stats if it was on - if ( mStatsp->frameStatsIsRunning() ) - { - llinfos << "Performance statistics configuration file deleted, not recording statistics" << llendl; - mStatsp->setReportPerformanceDuration( 0.f ); - } - return true; - } - } - - F32 duration = 0.f; - F32 interval = 0.f; - S32 flags = LLPerfBlock::LLSTATS_BASIC_STATS; - - const char * w = "duration"; - if (stats_config.has(w)) - { - duration = (F32)stats_config[w].asReal(); - } - w = "interval"; - if (stats_config.has(w)) - { - interval = (F32)stats_config[w].asReal(); - } - w = "flags"; - if (stats_config.has(w)) - { - flags = (S32)stats_config[w].asInteger(); - if (flags == LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS && - duration > 0) - { // No flags passed in, but have a duration, so reset to basic stats - flags = LLPerfBlock::LLSTATS_BASIC_STATS; - } - } - - mStatsp->setReportPerformanceDuration( duration, flags ); - mStatsp->setReportPerformanceInterval( interval ); - - if ( duration > 0 ) - { - if ( interval == 0.f ) - { - llinfos << "Recording performance stats every frame for " << duration << " sec" << llendl; - } - else - { - llinfos << "Recording performance stats every " << interval << " seconds for " << duration << " seconds" << llendl; - } - } - else - { - llinfos << "Performance stats recording turned off" << llendl; - } - return true; -} - - -//------------------------------------------------------------------------ - -LLPerfStats::LLPerfStats(const std::string& process_name, S32 process_pid) : - mFrameStatsFileFailure(FALSE), - mSkipFirstFrameStats(FALSE), - mProcessName(process_name), - mProcessPID(process_pid), - mReportPerformanceStatInterval(1.f), - mReportPerformanceStatEnd(0.0) -{ } - -LLPerfStats::~LLPerfStats() -{ - LLPerfBlock::clearDynamicStats(); - mFrameStatsFile.close(); -} - -void LLPerfStats::init() -{ - // Initialize the stats config file instance. - (void) LLStatsConfigFile::instance().init(this); - (void) LLStatsConfigFile::instance().checkAndReload(); -} - -// Open file for statistics -void LLPerfStats::openPerfStatsFile() -{ - if ( !mFrameStatsFile - && !mFrameStatsFileFailure ) - { - std::string stats_file = llformat("/dev/shm/simperf/%s_proc.%d.llsd", mProcessName.c_str(), mProcessPID); - mFrameStatsFile.close(); - mFrameStatsFile.clear(); - mFrameStatsFile.open(stats_file, llofstream::out); - if ( mFrameStatsFile.fail() ) - { - llinfos << "Error opening statistics log file " << stats_file << llendl; - mFrameStatsFileFailure = TRUE; - } - else - { - LLSD process_info = LLSD::emptyMap(); - process_info["name"] = mProcessName; - process_info["pid"] = (LLSD::Integer) mProcessPID; - process_info["stat_rate"] = (LLSD::Integer) mReportPerformanceStatInterval; - // Add process-specific info. - addProcessHeaderInfo(process_info); - - mFrameStatsFile << LLSDNotationStreamer(process_info) << std::endl; - } - } -} - -// Dump out performance metrics over some time interval -void LLPerfStats::dumpIntervalPerformanceStats() -{ - // Ensure output file is OK - openPerfStatsFile(); - - if ( mFrameStatsFile ) - { - LLSD stats = LLSD::emptyMap(); - - LLStatAccum::TimeScale scale; - if ( getReportPerformanceInterval() == 0.f ) - { - scale = LLStatAccum::SCALE_PER_FRAME; - } - else if ( getReportPerformanceInterval() < 0.5f ) - { - scale = LLStatAccum::SCALE_100MS; - } - else - { - scale = LLStatAccum::SCALE_SECOND; - } - - // Write LLSD into log - stats["utc_time"] = (LLSD::String) LLError::utcTime(); - stats["timestamp"] = U64_to_str((totalTime() / 1000) + (gUTCOffset * 1000)); // milliseconds since epoch - stats["frame_number"] = (LLSD::Integer) LLFrameTimer::getFrameCount(); - - // Add process-specific frame info. - addProcessFrameInfo(stats, scale); - LLPerfBlock::addStatsToLLSDandReset( stats, scale ); - - mFrameStatsFile << LLSDNotationStreamer(stats) << std::endl; - } -} - -// Set length of performance stat recording. -// If turning stats on, caller must provide flags -void LLPerfStats::setReportPerformanceDuration( F32 seconds, S32 flags /* = LLSTATS_NO_OPTIONAL_STATS */ ) -{ - if ( seconds <= 0.f ) - { - mReportPerformanceStatEnd = 0.0; - LLPerfBlock::setStatsFlags(LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS); // Make sure all recording is off - mFrameStatsFile.close(); - LLPerfBlock::clearDynamicStats(); - } - else - { - mReportPerformanceStatEnd = LLFrameTimer::getElapsedSeconds() + ((F64) seconds); - // Clear failure flag to try and create the log file once - mFrameStatsFileFailure = FALSE; - mSkipFirstFrameStats = TRUE; // Skip the first report (at the end of this frame) - LLPerfBlock::setStatsFlags(flags); - } -} - -void LLPerfStats::updatePerFrameStats() -{ - (void) LLStatsConfigFile::instance().checkAndReload(); - static LLFrameTimer performance_stats_timer; - if ( frameStatsIsRunning() ) - { - if ( mReportPerformanceStatInterval == 0 ) - { // Record info every frame - if ( mSkipFirstFrameStats ) - { // Skip the first time - was started this frame - mSkipFirstFrameStats = FALSE; - } - else - { - dumpIntervalPerformanceStats(); - } - } - else - { - performance_stats_timer.setTimerExpirySec( getReportPerformanceInterval() ); - if (performance_stats_timer.checkExpirationAndReset( mReportPerformanceStatInterval )) - { - dumpIntervalPerformanceStats(); - } - } - - if ( LLFrameTimer::getElapsedSeconds() > mReportPerformanceStatEnd ) - { // Reached end of time, clear it to stop reporting - setReportPerformanceDuration(0.f); // Don't set mReportPerformanceStatEnd directly - llinfos << "Recording performance stats completed" << llendl; - } - } -} - - -//------------------------------------------------------------------------ - -U64 LLStatAccum::sScaleTimes[NUM_SCALES] = -{ - USEC_PER_SEC / 10, // 100 millisec - USEC_PER_SEC * 1, // seconds - USEC_PER_SEC * 60, // minutes -#if ENABLE_LONG_TIME_STATS - // enable these when more time scales are desired - USEC_PER_SEC * 60*60, // hours - USEC_PER_SEC * 24*60*60, // days - USEC_PER_SEC * 7*24*60*60, // weeks -#endif -}; - - - -LLStatAccum::LLStatAccum(bool useFrameTimer) - : mUseFrameTimer(useFrameTimer), - mRunning(FALSE), - mLastTime(0), - mLastSampleValue(0.0), - mLastSampleValid(FALSE) -{ -} - -LLStatAccum::~LLStatAccum() -{ -} - - - -void LLStatAccum::reset(U64 when) -{ - mRunning = TRUE; - mLastTime = when; - - for (int i = 0; i < NUM_SCALES; ++i) - { - mBuckets[i].accum = 0.0; - mBuckets[i].endTime = when + sScaleTimes[i]; - mBuckets[i].lastValid = false; - } -} - -void LLStatAccum::sum(F64 value) -{ - sum(value, getCurrentUsecs()); -} - -void LLStatAccum::sum(F64 value, U64 when) -{ - if (!mRunning) - { - reset(when); - return; - } - if (when < mLastTime) - { - // This happens a LOT on some dual core systems. - lldebugs << "LLStatAccum::sum clock has gone backwards from " - << mLastTime << " to " << when << ", resetting" << llendl; - - reset(when); - return; - } - - // how long is this value for - U64 timeSpan = when - mLastTime; - - for (int i = 0; i < NUM_SCALES; ++i) - { - Bucket& bucket = mBuckets[i]; - - if (when < bucket.endTime) - { - bucket.accum += value; - } - else - { - U64 timeScale = sScaleTimes[i]; - - U64 timeLeft = when - bucket.endTime; - // how much time is left after filling this bucket - - if (timeLeft < timeScale) - { - F64 valueLeft = value * timeLeft / timeSpan; - - bucket.lastValid = true; - bucket.lastAccum = bucket.accum + (value - valueLeft); - bucket.accum = valueLeft; - bucket.endTime += timeScale; - } - else - { - U64 timeTail = timeLeft % timeScale; - - bucket.lastValid = true; - bucket.lastAccum = value * timeScale / timeSpan; - bucket.accum = value * timeTail / timeSpan; - bucket.endTime += (timeLeft - timeTail) + timeScale; - } - } - } - - mLastTime = when; -} - - -F32 LLStatAccum::meanValue(TimeScale scale) const -{ - if (!mRunning) - { - return 0.0; - } - if ( scale == SCALE_PER_FRAME ) - { // Per-frame not supported here - scale = SCALE_100MS; - } - - if (scale < 0 || scale >= NUM_SCALES) - { - llwarns << "llStatAccum::meanValue called for unsupported scale: " - << scale << llendl; - return 0.0; - } - - const Bucket& bucket = mBuckets[scale]; - - F64 value = bucket.accum; - U64 timeLeft = bucket.endTime - mLastTime; - U64 scaleTime = sScaleTimes[scale]; - - if (bucket.lastValid) - { - value += bucket.lastAccum * timeLeft / scaleTime; - } - else if (timeLeft < scaleTime) - { - value *= scaleTime / (scaleTime - timeLeft); - } - else - { - value = 0.0; - } - - return (F32)(value / scaleTime); -} - - -U64 LLStatAccum::getCurrentUsecs() const -{ - if (mUseFrameTimer) - { - return LLFrameTimer::getTotalTime(); - } - else - { - return totalTime(); - } -} - - -// ------------------------------------------------------------------------ - -LLStatRate::LLStatRate(bool use_frame_timer) - : LLStatAccum(use_frame_timer) -{ -} - -void LLStatRate::count(U32 value) -{ - sum((F64)value * sScaleTimes[SCALE_SECOND]); -} - - -void LLStatRate::mark() - { - // Effectively the same as count(1), but sets mLastSampleValue - U64 when = getCurrentUsecs(); - - if ( mRunning - && (when > mLastTime) ) - { // Set mLastSampleValue to the time from the last mark() - F64 duration = ((F64)(when - mLastTime)) / sScaleTimes[SCALE_SECOND]; - if ( duration > 0.0 ) - { - mLastSampleValue = 1.0 / duration; - } - else - { - mLastSampleValue = 0.0; - } - } - - sum( (F64) sScaleTimes[SCALE_SECOND], when); - } - - -// ------------------------------------------------------------------------ - - -LLStatMeasure::LLStatMeasure(bool use_frame_timer) - : LLStatAccum(use_frame_timer) -{ -} - -void LLStatMeasure::sample(F64 value) -{ - U64 when = getCurrentUsecs(); - - if (mLastSampleValid) - { - F64 avgValue = (value + mLastSampleValue) / 2.0; - F64 interval = (F64)(when - mLastTime); - - sum(avgValue * interval, when); - } - else - { - reset(when); - } - - mLastSampleValid = TRUE; - mLastSampleValue = value; -} - - -// ------------------------------------------------------------------------ - -LLStatTime::LLStatTime(const std::string & key) - : LLStatAccum(false), - mFrameNumber(LLFrameTimer::getFrameCount()), - mTotalTimeInFrame(0), - mKey(key) -#if LL_DEBUG - , mRunning(FALSE) -#endif -{ -} - -void LLStatTime::start() -{ - // Reset frame accumluation if the frame number has changed - U32 frame_number = LLFrameTimer::getFrameCount(); - if ( frame_number != mFrameNumber ) - { - mFrameNumber = frame_number; - mTotalTimeInFrame = 0; - } - - sum(0.0); - -#if LL_DEBUG - // Shouldn't be running already - llassert( !mRunning ); - mRunning = TRUE; -#endif -} - -void LLStatTime::stop() -{ - U64 end_time = getCurrentUsecs(); - U64 duration = end_time - mLastTime; - sum(F64(duration), end_time); - //llinfos << "mTotalTimeInFrame incremented from " << mTotalTimeInFrame << " to " << (mTotalTimeInFrame + duration) << llendl; - mTotalTimeInFrame += duration; - -#if LL_DEBUG - mRunning = FALSE; -#endif -} - -/* virtual */ F32 LLStatTime::meanValue(TimeScale scale) const -{ - if ( LLStatAccum::SCALE_PER_FRAME == scale ) - { - return (F32)mTotalTimeInFrame; - } - else - { - return LLStatAccum::meanValue(scale); - } -} - - -// ------------------------------------------------------------------------ - - -// Use this constructor for pre-defined LLStatTime objects -LLPerfBlock::LLPerfBlock(LLStatTime* stat ) : mPredefinedStat(stat), mDynamicStat(NULL) -{ - if (mPredefinedStat) - { - // If dynamic stats are turned on, this will create a separate entry in the stat map. - initDynamicStat(mPredefinedStat->mKey); - - // Start predefined stats. These stats are not part of the stat map. - mPredefinedStat->start(); - } -} - -// Use this constructor for normal, optional LLPerfBlock time slices -LLPerfBlock::LLPerfBlock( const char* key ) : mPredefinedStat(NULL), mDynamicStat(NULL) -{ - if ((sStatsFlags & LLSTATS_BASIC_STATS) == 0) - { // These are off unless the base set is enabled - return; - } - - initDynamicStat(key); -} - - -// Use this constructor for dynamically created LLPerfBlock time slices -// that are only enabled by specific control flags -LLPerfBlock::LLPerfBlock( const char* key1, const char* key2, S32 flags ) : mPredefinedStat(NULL), mDynamicStat(NULL) -{ - if ((sStatsFlags & flags) == 0) - { - return; - } - - if (NULL == key2 || strlen(key2) == 0) - { - initDynamicStat(key1); - } - else - { - std::ostringstream key; - key << key1 << "_" << key2; - initDynamicStat(key.str()); - } -} - -// Set up the result data map if dynamic stats are enabled -void LLPerfBlock::initDynamicStat(const std::string& key) -{ - // Early exit if dynamic stats aren't enabled. - if (sStatsFlags == LLSTATS_NO_OPTIONAL_STATS) - return; - - mLastPath = sCurrentStatPath; // Save and restore current path - sCurrentStatPath += "/" + key; // Add key to current path - - // See if the LLStatTime object already exists - stat_map_t::iterator iter = sStatMap.find(sCurrentStatPath); - if ( iter == sStatMap.end() ) - { - // StatEntry object doesn't exist, so create it - mDynamicStat = new StatEntry( key ); - sStatMap[ sCurrentStatPath ] = mDynamicStat; // Set the entry for this path - } - else - { - // Found this path in the map, use the object there - mDynamicStat = (*iter).second; // Get StatEntry for the current path - } - - if (mDynamicStat) - { - mDynamicStat->mStat.start(); - mDynamicStat->mCount++; - } - else - { - llwarns << "Initialized NULL dynamic stat at '" << sCurrentStatPath << "'" << llendl; - sCurrentStatPath = mLastPath; - } -} - - -// Destructor does the time accounting -LLPerfBlock::~LLPerfBlock() -{ - if (mPredefinedStat) mPredefinedStat->stop(); - if (mDynamicStat) - { - mDynamicStat->mStat.stop(); - sCurrentStatPath = mLastPath; // Restore the path in case sStatsEnabled changed during this block - } -} - - -// Clear the map of any dynamic stats. Static routine -void LLPerfBlock::clearDynamicStats() -{ - std::for_each(sStatMap.begin(), sStatMap.end(), DeletePairedPointer()); - sStatMap.clear(); -} - -// static - Extract the stat info into LLSD -void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, - LLStatAccum::TimeScale scale ) -{ - // If we aren't in per-frame scale, we need to go from second to microsecond. - U32 scale_adjustment = 1; - if (LLStatAccum::SCALE_PER_FRAME != scale) - { - scale_adjustment = USEC_PER_SEC; - } - stat_map_t::iterator iter = sStatMap.begin(); - for ( ; iter != sStatMap.end(); ++iter ) - { // Put the entry into LLSD "/full/path/to/stat/" = microsecond total time - const std::string & stats_full_path = (*iter).first; - - StatEntry * stat = (*iter).second; - if (stat) - { - if (stat->mCount > 0) - { - stats[stats_full_path] = LLSD::emptyMap(); - stats[stats_full_path]["us"] = (LLSD::Integer) (scale_adjustment * stat->mStat.meanValue(scale)); - if (stat->mCount > 1) - { - stats[stats_full_path]["count"] = (LLSD::Integer) stat->mCount; - } - stat->mCount = 0; - } - } - else - { // Shouldn't have a NULL pointer in the map. - llwarns << "Unexpected NULL dynamic stat at '" << stats_full_path << "'" << llendl; - } - } -} - - -// ------------------------------------------------------------------------ - LLTimer LLStat::sTimer; LLFrameTimer LLStat::sFrameTimer; -void LLStat::init() +void LLStat::reset() { - llassert(mNumBins > 0); mNumValues = 0; mLastValue = 0.f; - mLastTime = 0.f; - mCurBin = (mNumBins-1); + delete[] mBins; + mBins = new ValueEntry[mNumBins]; + mCurBin = mNumBins-1; mNextBin = 0; - mBins = new F32[mNumBins]; - mBeginTime = new F64[mNumBins]; - mTime = new F64[mNumBins]; - mDT = new F32[mNumBins]; - for (U32 i = 0; i < mNumBins; i++) - { - mBins[i] = 0.f; - mBeginTime[i] = 0.0; - mTime[i] = 0.0; - mDT[i] = 0.f; - } +} + +LLStat::LLStat(std::string name, S32 num_bins, BOOL use_frame_timer) +: mUseFrameTimer(use_frame_timer), + mNumBins(num_bins), + mName(name), + mBins(NULL) +{ + llassert(mNumBins > 0); + mLastTime = 0.f; + + reset(); if (!mName.empty()) { @@ -787,27 +81,9 @@ LLStat::stat_map_t& LLStat::getStatList() return *stat_list; } -LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) - : mUseFrameTimer(use_frame_timer), - mNumBins(num_bins) -{ - init(); -} - -LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer) - : mUseFrameTimer(use_frame_timer), - mNumBins(num_bins), - mName(name) -{ - init(); -} - LLStat::~LLStat() { delete[] mBins; - delete[] mBeginTime; - delete[] mTime; - delete[] mDT; if (!mName.empty()) { @@ -819,76 +95,15 @@ LLStat::~LLStat() } } -void LLStat::reset() -{ - U32 i; - - mNumValues = 0; - mLastValue = 0.f; - mCurBin = (mNumBins-1); - delete[] mBins; - delete[] mBeginTime; - delete[] mTime; - delete[] mDT; - mBins = new F32[mNumBins]; - mBeginTime = new F64[mNumBins]; - mTime = new F64[mNumBins]; - mDT = new F32[mNumBins]; - for (i = 0; i < mNumBins; i++) - { - mBins[i] = 0.f; - mBeginTime[i] = 0.0; - mTime[i] = 0.0; - mDT[i] = 0.f; - } -} - -void LLStat::setBeginTime(const F64 time) -{ - mBeginTime[mNextBin] = time; -} - -void LLStat::addValueTime(const F64 time, const F32 value) -{ - if (mNumValues < mNumBins) - { - mNumValues++; - } - - // Increment the bin counters. - mCurBin++; - if ((U32)mCurBin == mNumBins) - { - mCurBin = 0; - } - mNextBin++; - if ((U32)mNextBin == mNumBins) - { - mNextBin = 0; - } - - mBins[mCurBin] = value; - mTime[mCurBin] = time; - mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]); - //this value is used to prime the min/max calls - mLastTime = mTime[mCurBin]; - mLastValue = value; - - // Set the begin time for the next stat segment. - mBeginTime[mNextBin] = mTime[mCurBin]; - mTime[mNextBin] = mTime[mCurBin]; - mDT[mNextBin] = 0.f; -} - void LLStat::start() { if (mUseFrameTimer) { - mBeginTime[mNextBin] = sFrameTimer.getElapsedSeconds(); + mBins[mNextBin].mBeginTime = sFrameTimer.getElapsedSeconds(); } else { - mBeginTime[mNextBin] = sTimer.getElapsedTimeF64(); + mBins[mNextBin].mBeginTime = sTimer.getElapsedTimeF64(); } } @@ -901,41 +116,41 @@ void LLStat::addValue(const F32 value) // Increment the bin counters. mCurBin++; - if ((U32)mCurBin == mNumBins) + if ((U32)mCurBin >= mNumBins) { mCurBin = 0; } mNextBin++; - if ((U32)mNextBin == mNumBins) + if ((U32)mNextBin >= mNumBins) { mNextBin = 0; } - mBins[mCurBin] = value; + mBins[mCurBin].mValue = value; if (mUseFrameTimer) { - mTime[mCurBin] = sFrameTimer.getElapsedSeconds(); + mBins[mCurBin].mTime = sFrameTimer.getElapsedSeconds(); } else { - mTime[mCurBin] = sTimer.getElapsedTimeF64(); + mBins[mCurBin].mTime = sTimer.getElapsedTimeF64(); } - mDT[mCurBin] = (F32)(mTime[mCurBin] - mBeginTime[mCurBin]); + mBins[mCurBin].mDT = (F32)(mBins[mCurBin].mTime - mBins[mCurBin].mBeginTime); //this value is used to prime the min/max calls - mLastTime = mTime[mCurBin]; + mLastTime = mBins[mCurBin].mTime; mLastValue = value; // Set the begin time for the next stat segment. - mBeginTime[mNextBin] = mTime[mCurBin]; - mTime[mNextBin] = mTime[mCurBin]; - mDT[mNextBin] = 0.f; + mBins[mNextBin].mBeginTime = mBins[mCurBin].mTime; + mBins[mNextBin].mTime = mBins[mCurBin].mTime; + mBins[mNextBin].mDT = 0.f; } F32 LLStat::getMax() const { - U32 i; + S32 i; F32 current_max = mLastValue; if (mNumBins == 0) { @@ -943,16 +158,16 @@ F32 LLStat::getMax() const } else { - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + for (i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - if (mBins[i] > current_max) + if (mBins[i].mValue > current_max) { - current_max = mBins[i]; + current_max = mBins[i].mValue; } } } @@ -961,17 +176,17 @@ F32 LLStat::getMax() const F32 LLStat::getMean() const { - U32 i; + S32 i; F32 current_mean = 0.f; - U32 samples = 0; - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + S32 samples = 0; + for (i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - current_mean += mBins[i]; + current_mean += mBins[i].mValue; samples++; } @@ -989,7 +204,7 @@ F32 LLStat::getMean() const F32 LLStat::getMin() const { - U32 i; + S32 i; F32 current_min = mLastValue; if (mNumBins == 0) @@ -998,56 +213,22 @@ F32 LLStat::getMin() const } else { - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + for (i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - if (mBins[i] < current_min) + if (mBins[i].mValue < current_min) { - current_min = mBins[i]; + current_min = mBins[i].mValue; } } } return current_min; } -F32 LLStat::getSum() const -{ - U32 i; - F32 sum = 0.f; - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == (U32)mNextBin) - { - continue; - } - sum += mBins[i]; - } - - return sum; -} - -F32 LLStat::getSumDuration() const -{ - U32 i; - F32 sum = 0.f; - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) - { - // Skip the bin we're currently filling. - if (i == (U32)mNextBin) - { - continue; - } - sum += mDT[i]; - } - - return sum; -} - F32 LLStat::getPrev(S32 age) const { S32 bin; @@ -1063,7 +244,7 @@ F32 LLStat::getPrev(S32 age) const // Bogus for bin we're currently working on. return 0.f; } - return mBins[bin]; + return mBins[bin].mValue; } F32 LLStat::getPrevPerSec(S32 age) const @@ -1081,7 +262,7 @@ F32 LLStat::getPrevPerSec(S32 age) const // Bogus for bin we're currently working on. return 0.f; } - return mBins[bin] / mDT[bin]; + return mBins[bin].mValue / mBins[bin].mDT; } F64 LLStat::getPrevBeginTime(S32 age) const @@ -1100,7 +281,7 @@ F64 LLStat::getPrevBeginTime(S32 age) const return 0.f; } - return mBeginTime[bin]; + return mBins[bin].mBeginTime; } F64 LLStat::getPrevTime(S32 age) const @@ -1119,69 +300,45 @@ F64 LLStat::getPrevTime(S32 age) const return 0.f; } - return mTime[bin]; + return mBins[bin].mTime; } -F32 LLStat::getBin(S32 bin) const -{ - return mBins[bin]; -} - -F32 LLStat::getBinPerSec(S32 bin) const -{ - return mBins[bin] / mDT[bin]; -} - -F64 LLStat::getBinBeginTime(S32 bin) const -{ - return mBeginTime[bin]; -} F64 LLStat::getBinTime(S32 bin) const { - return mTime[bin]; + return mBins[bin].mTime; } F32 LLStat::getCurrent() const { - return mBins[mCurBin]; + return mBins[mCurBin].mValue; } F32 LLStat::getCurrentPerSec() const { - return mBins[mCurBin] / mDT[mCurBin]; -} - -F64 LLStat::getCurrentBeginTime() const -{ - return mBeginTime[mCurBin]; -} - -F64 LLStat::getCurrentTime() const -{ - return mTime[mCurBin]; + return mBins[mCurBin].mValue / mBins[mCurBin].mDT; } F32 LLStat::getCurrentDuration() const { - return mDT[mCurBin]; + return mBins[mCurBin].mDT; } F32 LLStat::getMeanPerSec() const { - U32 i; + S32 i; F32 value = 0.f; F32 dt = 0.f; - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + for (i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - value += mBins[i]; - dt += mDT[i]; + value += mBins[i].mValue; + dt += mBins[i].mDT; } if (dt > 0.f) @@ -1197,14 +354,14 @@ F32 LLStat::getMeanPerSec() const F32 LLStat::getMeanDuration() const { F32 dur = 0.0f; - U32 count = 0; - for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++) + S32 count = 0; + for (S32 i=0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - dur += mDT[i]; + dur += mBins[i].mDT; count++; } @@ -1221,74 +378,63 @@ F32 LLStat::getMeanDuration() const F32 LLStat::getMaxPerSec() const { - U32 i; F32 value; if (mNextBin != 0) { - value = mBins[0]/mDT[0]; + value = mBins[0].mValue/mBins[0].mDT; } else if (mNumValues > 0) { - value = mBins[1]/mDT[1]; + value = mBins[1].mValue/mBins[1].mDT; } else { value = 0.f; } - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + for (S32 i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - value = llmax(value, mBins[i]/mDT[i]); + value = llmax(value, mBins[i].mValue/mBins[i].mDT); } return value; } F32 LLStat::getMinPerSec() const { - U32 i; + S32 i; F32 value; if (mNextBin != 0) { - value = mBins[0]/mDT[0]; + value = mBins[0].mValue/mBins[0].mDT; } else if (mNumValues > 0) { - value = mBins[1]/mDT[1]; + value = mBins[1].mValue/mBins[0].mDT; } else { value = 0.f; } - for (i = 0; (i < mNumBins) && (i < mNumValues); i++) + for (i = 0; (i < (S32)mNumBins) && (i < (S32)mNumValues); i++) { // Skip the bin we're currently filling. - if (i == (U32)mNextBin) + if (i == mNextBin) { continue; } - value = llmin(value, mBins[i]/mDT[i]); + value = llmin(value, mBins[i].mValue/mBins[i].mDT); } return value; } -F32 LLStat::getMinDuration() const -{ - F32 dur = 0.0f; - for (U32 i=0; (i < mNumBins) && (i < mNumValues); i++) - { - dur = llmin(dur, mDT[i]); - } - return dur; -} - U32 LLStat::getNumValues() const { return mNumValues; diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 1a8404cc0..12737a8ce 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -27,294 +27,52 @@ #ifndef LL_LLSTAT_H #define LL_LLSTAT_H -#include #include #include "lltimer.h" #include "llframetimer.h" -#include "llfile.h" class LLSD; -// Set this if longer stats are needed -#define ENABLE_LONG_TIME_STATS 0 - -// -// Accumulates statistics for an arbitrary length of time. -// Does this by maintaining a chain of accumulators, each one -// accumulation the results of the parent. Can scale to arbitrary -// amounts of time with very low memory cost. -// - -class LL_COMMON_API LLStatAccum -{ -protected: - LLStatAccum(bool use_frame_timer); - virtual ~LLStatAccum(); - -public: - enum TimeScale { - SCALE_100MS, - SCALE_SECOND, - SCALE_MINUTE, -#if ENABLE_LONG_TIME_STATS - SCALE_HOUR, - SCALE_DAY, - SCALE_WEEK, -#endif - NUM_SCALES, // Use to size storage arrays - SCALE_PER_FRAME // For latest frame information - should be after NUM_SCALES since this doesn't go into the time buckets - }; - - static U64 sScaleTimes[NUM_SCALES]; - - virtual F32 meanValue(TimeScale scale) const; - // see the subclasses for the specific meaning of value - - F32 meanValueOverLast100ms() const { return meanValue(SCALE_100MS); } - F32 meanValueOverLastSecond() const { return meanValue(SCALE_SECOND); } - F32 meanValueOverLastMinute() const { return meanValue(SCALE_MINUTE); } - - void reset(U64 when); - - void sum(F64 value); - void sum(F64 value, U64 when); - - U64 getCurrentUsecs() const; - // Get current microseconds based on timer type - - BOOL mUseFrameTimer; - BOOL mRunning; - - U64 mLastTime; - - struct Bucket - { - Bucket() : - accum(0.0), - endTime(0), - lastValid(false), - lastAccum(0.0) - {} - - F64 accum; - U64 endTime; - - bool lastValid; - F64 lastAccum; - }; - - Bucket mBuckets[NUM_SCALES]; - - BOOL mLastSampleValid; - F64 mLastSampleValue; -}; - -class LL_COMMON_API LLStatMeasure : public LLStatAccum - // gathers statistics about things that are measured - // ex.: tempature, time dilation -{ -public: - LLStatMeasure(bool use_frame_timer = true); - - void sample(F64); - void sample(S32 v) { sample((F64)v); } - void sample(U32 v) { sample((F64)v); } - void sample(S64 v) { sample((F64)v); } - void sample(U64 v) { sample((F64)v); } -}; - - -class LL_COMMON_API LLStatRate : public LLStatAccum - // gathers statistics about things that can be counted over time - // ex.: LSL instructions executed, messages sent, simulator frames completed - // renders it in terms of rate of thing per second -{ -public: - LLStatRate(bool use_frame_timer = true); - - void count(U32); - // used to note that n items have occured - - void mark(); - // used for counting the rate thorugh a point in the code -}; - - -class LL_COMMON_API LLStatTime : public LLStatAccum - // gathers statistics about time spent in a block of code - // measure average duration per second in the block -{ -public: - LLStatTime( const std::string & key = "undefined" ); - - U32 mFrameNumber; // Current frame number - U64 mTotalTimeInFrame; // Total time (microseconds) accumulated during the last frame - - void setKey( const std::string & key ) { mKey = key; }; - - virtual F32 meanValue(TimeScale scale) const; - -private: - void start(); // Start and stop measuring time block - void stop(); - - std::string mKey; // Tag representing this time block - -#if LL_DEBUG - BOOL mRunning; // TRUE if start() has been called -#endif - - friend class LLPerfBlock; -}; - -// ---------------------------------------------------------------------------- - - -// Use this class on the stack to record statistics about an area of code -class LL_COMMON_API LLPerfBlock -{ -public: - struct StatEntry - { - StatEntry(const std::string& key) : mStat(LLStatTime(key)), mCount(0) {} - LLStatTime mStat; - U32 mCount; - }; - typedef std::map stat_map_t; - - // Use this constructor for pre-defined LLStatTime objects - LLPerfBlock(LLStatTime* stat); - - // Use this constructor for normal, optional LLPerfBlock time slices - LLPerfBlock( const char* key ); - - // Use this constructor for dynamically created LLPerfBlock time slices - // that are only enabled by specific control flags - LLPerfBlock( const char* key1, const char* key2, S32 flags = LLSTATS_BASIC_STATS ); - - ~LLPerfBlock(); - - enum - { // Stats bitfield flags - LLSTATS_NO_OPTIONAL_STATS = 0x00, // No optional stats gathering, just pre-defined LLStatTime objects - LLSTATS_BASIC_STATS = 0x01, // Gather basic optional runtime stats - LLSTATS_SCRIPT_FUNCTIONS = 0x02, // Include LSL function calls - }; - static void setStatsFlags( S32 flags ) { sStatsFlags = flags; }; - static S32 getStatsFlags() { return sStatsFlags; }; - - static void clearDynamicStats(); // Reset maps to clear out dynamic objects - static void addStatsToLLSDandReset( LLSD & stats, // Get current information and clear time bin - LLStatAccum::TimeScale scale ); - -private: - // Initialize dynamically created LLStatTime objects - void initDynamicStat(const std::string& key); - - std::string mLastPath; // Save sCurrentStatPath when this is called - LLStatTime * mPredefinedStat; // LLStatTime object to get data - StatEntry * mDynamicStat; // StatEntryobject to get data - - static S32 sStatsFlags; // Control what is being recorded - static stat_map_t sStatMap; // Map full path string to LLStatTime objects - static std::string sCurrentStatPath; // Something like "frame/physics/physics step" -}; - -// ---------------------------------------------------------------------------- - -class LL_COMMON_API LLPerfStats -{ -public: - LLPerfStats(const std::string& process_name = "unknown", S32 process_pid = 0); - virtual ~LLPerfStats(); - - virtual void init(); // Reset and start all stat timers - virtual void updatePerFrameStats(); - // Override these function to add process-specific information to the performance log header and per-frame logging. - virtual void addProcessHeaderInfo(LLSD& info) { /* not implemented */ } - virtual void addProcessFrameInfo(LLSD& info, LLStatAccum::TimeScale scale) { /* not implemented */ } - - // High-resolution frame stats - BOOL frameStatsIsRunning() { return (mReportPerformanceStatEnd > 0.); }; - F32 getReportPerformanceInterval() const { return mReportPerformanceStatInterval; }; - void setReportPerformanceInterval( F32 interval ) { mReportPerformanceStatInterval = interval; }; - void setReportPerformanceDuration( F32 seconds, S32 flags = LLPerfBlock::LLSTATS_NO_OPTIONAL_STATS ); - void setProcessName(const std::string& process_name) { mProcessName = process_name; } - void setProcessPID(S32 process_pid) { mProcessPID = process_pid; } - -protected: - void openPerfStatsFile(); // Open file for high resolution metrics logging - void dumpIntervalPerformanceStats(); - - llofstream mFrameStatsFile; // File for per-frame stats - BOOL mFrameStatsFileFailure; // Flag to prevent repeat opening attempts - BOOL mSkipFirstFrameStats; // Flag to skip one (partial) frame report - std::string mProcessName; - S32 mProcessPID; - -private: - F32 mReportPerformanceStatInterval; // Seconds between performance stats - F64 mReportPerformanceStatEnd; // End time (seconds) for performance stats -}; - // ---------------------------------------------------------------------------- class LL_COMMON_API LLStat { private: typedef std::multimap stat_map_t; - void init(); static stat_map_t& getStatList(); public: - LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); - LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(std::string name = std::string(), S32 num_bins = 32, BOOL use_frame_timer = FALSE); ~LLStat(); - void reset(); - void start(); // Start the timer for the current "frame", otherwise uses the time tracked from // the last addValue + void reset(); void addValue(const F32 value = 1.f); // Adds the current value being tracked, and tracks the DT. void addValue(const S32 value) { addValue((F32)value); } void addValue(const U32 value) { addValue((F32)value); } - - void setBeginTime(const F64 time); - void addValueTime(const F64 time, const F32 value = 1.f); S32 getCurBin() const; S32 getNextBin() const; - F32 getCurrent() const; - F32 getCurrentPerSec() const; - F64 getCurrentBeginTime() const; - F64 getCurrentTime() const; - F32 getCurrentDuration() const; - F32 getPrev(S32 age) const; // Age is how many "addValues" previously - zero is current F32 getPrevPerSec(S32 age) const; // Age is how many "addValues" previously - zero is current + F32 getCurrent() const; + F32 getCurrentPerSec() const; + F32 getCurrentDuration() const; + F64 getPrevBeginTime(S32 age) const; F64 getPrevTime(S32 age) const; - - F32 getBin(S32 bin) const; - F32 getBinPerSec(S32 bin) const; - F64 getBinBeginTime(S32 bin) const; F64 getBinTime(S32 bin) const; - F32 getMax() const; - F32 getMaxPerSec() const; - - F32 getMean() const; - F32 getMeanPerSec() const; - F32 getMeanDuration() const; - F32 getMin() const; F32 getMinPerSec() const; - F32 getMinDuration() const; - - F32 getSum() const; - F32 getSumDuration() const; + F32 getMean() const; + F32 getMeanPerSec() const; + F32 getMeanDuration() const; + F32 getMax() const; + F32 getMaxPerSec() const; U32 getNumValues() const; S32 getNumBins() const; @@ -326,10 +84,21 @@ private: U32 mNumBins; F32 mLastValue; F64 mLastTime; - F32 *mBins; - F64 *mBeginTime; - F64 *mTime; - F32 *mDT; + + struct ValueEntry + { + ValueEntry() + : mValue(0.f), + mBeginTime(0.0), + mTime(0.0), + mDT(0.f) + {} + F32 mValue; + F64 mBeginTime; + F64 mTime; + F32 mDT; + }; + ValueEntry* mBins; S32 mCurBin; S32 mNextBin; diff --git a/indra/llmessage/llcircuit.cpp b/indra/llmessage/llcircuit.cpp index 2ae76ab5e..6bb435f53 100644 --- a/indra/llmessage/llcircuit.cpp +++ b/indra/llmessage/llcircuit.cpp @@ -680,7 +680,6 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID); mLastPacketGap = 0; - mOutOfOrderRate.count(0); return; } @@ -776,7 +775,6 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent) } } - mOutOfOrderRate.count(gap); mLastPacketGap = gap; } diff --git a/indra/llmessage/llcircuit.h b/indra/llmessage/llcircuit.h index cd7576efa..13b0e9e49 100644 --- a/indra/llmessage/llcircuit.h +++ b/indra/llmessage/llcircuit.h @@ -40,7 +40,6 @@ #include "llpacketack.h" #include "lluuid.h" #include "llthrottle.h" -#include "llstat.h" // // Constants @@ -126,8 +125,6 @@ public: S32 getUnackedPacketCount() const { return mUnackedPacketCount; } S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } F64 getNextPingSendTime() const { return mNextPingSendTime; } - F32 getOutOfOrderRate(LLStatAccum::TimeScale scale = LLStatAccum::SCALE_MINUTE) - { return mOutOfOrderRate.meanValue(scale); } U32 getLastPacketGap() const { return mLastPacketGap; } LLHost getHost() const { return mHost; } F64 getLastPacketInTime() const { return mLastPacketInTime; } @@ -275,7 +272,6 @@ protected: LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers S32 mCurrentResendCount; // Number of resent packets since last spam - LLStatRate mOutOfOrderRate; // Rate of out of order packets coming in. U32 mLastPacketGap; // Gap in sequence number of last packet. const F32 mHeartbeatInterval; diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp index 6e2ec7f9b..9ce06f147 100644 --- a/indra/llmessage/lliohttpserver.cpp +++ b/indra/llmessage/lliohttpserver.cpp @@ -141,6 +141,11 @@ private: }; static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_GET("HTTP Get"); +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PUT("HTTP Put"); +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_POST("HTTP Post"); +static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_DELETE("HTTP Delete"); + LLIOPipe::EStatus LLHTTPPipe::process_impl( const LLChannelDescriptors& channels, buffer_ptr_t& buffer, @@ -177,12 +182,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; if(verb == HTTP_VERB_GET) { - LLPerfBlock getblock("http_get"); + LLFastTimer _(FTM_PROCESS_HTTP_GET); mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_PUT) { - LLPerfBlock putblock("http_put"); + LLFastTimer _(FTM_PROCESS_HTTP_PUT); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -198,7 +203,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_POST) { - LLPerfBlock postblock("http_post"); + LLFastTimer _(FTM_PROCESS_HTTP_POST); LLSD input; if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) { @@ -214,7 +219,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl( } else if(verb == HTTP_VERB_DELETE) { - LLPerfBlock delblock("http_delete"); + LLFastTimer _(FTM_PROCESS_HTTP_DELETE); mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); } else if(verb == HTTP_VERB_OPTIONS) diff --git a/indra/llmessage/llmessagetemplate.h b/indra/llmessage/llmessagetemplate.h index 16d825d33..a91a8f775 100644 --- a/indra/llmessage/llmessagetemplate.h +++ b/indra/llmessage/llmessagetemplate.h @@ -364,7 +364,6 @@ public: { if (mHandlerFunc) { - LLPerfBlock msg_cb_time("msg_cb", mName); mHandlerFunc(msgsystem, mUserData); return TRUE; } diff --git a/indra/llmessage/llpumpio.cpp b/indra/llmessage/llpumpio.cpp index e6c6a42d6..d4f6f59b1 100644 --- a/indra/llmessage/llpumpio.cpp +++ b/indra/llmessage/llpumpio.cpp @@ -454,6 +454,7 @@ void LLPumpIO::pump() } static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); +static LLFastTimer::DeclareTimer FTM_PUMP_POLL("Pump Poll"); LLPumpIO::current_chain_t LLPumpIO::removeRunningChain(LLPumpIO::current_chain_t& run_chain) { @@ -549,7 +550,7 @@ void LLPumpIO::pump(const S32& poll_timeout) S32 count = 0; S32 client_id = 0; { - LLPerfBlock polltime("pump_poll"); + LLFastTimer _(FTM_PUMP_POLL); apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); } PUMP_DEBUG; diff --git a/indra/newview/llfloaterjoystick.cpp b/indra/newview/llfloaterjoystick.cpp index e5811671e..19e1b3e2c 100644 --- a/indra/newview/llfloaterjoystick.cpp +++ b/indra/newview/llfloaterjoystick.cpp @@ -106,7 +106,8 @@ BOOL LLFloaterJoystick::postBuild() for (U32 i = 0; i < 6; i++) { axis.setArg("[NUM]", llformat("%d", i)); - mAxisStats[i] = new LLStat(4); + std::string stat_name(llformat("Joystick axis %d", i)); + mAxisStats[i] = new LLStat(stat_name,4); mAxisStatsBar[i] = mAxisStatsView->addStat(axis, mAxisStats[i]); mAxisStatsBar[i]->mMinBar = -range; mAxisStatsBar[i]->mMaxBar = range; diff --git a/indra/newview/llmemoryview.cpp b/indra/newview/llmemoryview.cpp index 5cba79d9d..e4815fbb1 100644 --- a/indra/newview/llmemoryview.cpp +++ b/indra/newview/llmemoryview.cpp @@ -104,6 +104,7 @@ void LLMemoryView::refreshProfile() mLines.clear(); +#if MEM_TRACK_MEM if(mAlloc->isProfiling()) { const LLAllocatorHeapProfile &prof = mAlloc->getProfile(); @@ -118,6 +119,7 @@ void LLMemoryView::refreshProfile() mLines.push_back(utf8string_to_wstring(ss.str())); } } +#endif } void LLMemoryView::draw() From a31ba15dbcd470319d0df7187b331fda900f17e5 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 20:49:17 -0600 Subject: [PATCH 13/18] Updated LLFloaterBuyContents --- indra/newview/llfloaterbuycontents.cpp | 114 +++++++++++++------------ indra/newview/llfloaterbuycontents.h | 15 ++-- 2 files changed, 67 insertions(+), 62 deletions(-) diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp index 0bde0cfee..56bd7ed1f 100644 --- a/indra/newview/llfloaterbuycontents.cpp +++ b/indra/newview/llfloaterbuycontents.cpp @@ -58,26 +58,36 @@ #include "hippogridmanager.h" -LLFloaterBuyContents* LLFloaterBuyContents::sInstance = NULL; - LLFloaterBuyContents::LLFloaterBuyContents() : LLFloater(std::string("floater_buy_contents"), std::string("FloaterBuyContentsRect"), LLStringUtil::null) { LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_contents.xml"); +} - childSetAction("cancel_btn", onClickCancel, this); - childSetAction("buy_btn", onClickBuy, this); +BOOL LLFloaterBuyContents::postBuild() +{ - childDisable("item_list"); - childDisable("buy_btn"); - childDisable("wear_check"); + getChild("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickCancel, this)); + getChild("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickBuy, this)); + + getChildView("item_list")->setEnabled(FALSE); + getChildView("buy_btn")->setEnabled(FALSE); + getChildView("wear_check")->setEnabled(FALSE); setDefaultBtn("cancel_btn"); // to avoid accidental buy (SL-43130) + + // Always center the dialog. User can change the size, + // but purchases are important and should be center screen. + // This also avoids problems where the user resizes the application window + // mid-session and the saved rect is off-center. + center(); + + return TRUE; } LLFloaterBuyContents::~LLFloaterBuyContents() { - sInstance = NULL; + removeVOInventoryListener(); } @@ -92,26 +102,20 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) return; } - // Create a new instance only if needed - if (sInstance) - { - LLScrollListCtrl* list = sInstance->getChild("item_list"); - if (list) list->deleteAllItems(); - } - else - { - sInstance = new LLFloaterBuyContents(); - } + LLFloaterBuyContents* floater = getInstance(); + LLScrollListCtrl* list = floater->getChild("item_list"); + if (list) + list->deleteAllItems(); - sInstance->open(); /*Flawfinder: ignore*/ - sInstance->setFocus(TRUE); - sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + floater->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection(); + floater->open(); /*Flawfinder: ignore*/ + floater->setFocus(TRUE); // Always center the dialog. User can change the size, // but purchases are important and should be center screen. // This also avoids problems where the user resizes the application window // mid-session and the saved rect is off-center. - sInstance->center(); + floater->center(); LLUUID owner_id; std::string owner_name; @@ -122,7 +126,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) return; } - sInstance->mSaleInfo = sale_info; + floater->mSaleInfo = sale_info; // Update the display LLSelectNode* node = selection->getFirstRootNode(); @@ -132,17 +136,17 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) gCacheName->getGroupName(owner_id, owner_name); } - sInstance->childSetTextArg("contains_text", "[NAME]", node->mName); - sInstance->childSetTextArg("buy_text", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); - sInstance->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice())); - sInstance->childSetTextArg("buy_text", "[NAME]", owner_name); + floater->getChild("contains_text")->setTextArg("[NAME]", node->mName); + floater->getChild("buy_text")->setTextArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); + floater->getChild("buy_text")->setTextArg("[AMOUNT]", llformat("%d", sale_info.getSalePrice())); + floater->getChild("buy_text")->setTextArg("[NAME]", owner_name); // Must do this after the floater is created, because // sometimes the inventory is already there and // the callback is called immediately. LLViewerObject* obj = selection->getFirstRootObject(); - sInstance->registerVOInventoryListener(obj,NULL); - sInstance->requestVOInventory(); + floater->registerVOInventoryListener(obj,NULL); + floater->requestVOInventory(); } @@ -157,23 +161,26 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, return; } - if (!inv) - { - llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged" - << llendl; - removeVOInventoryListener(); - return; - } - - LLCtrlListInterface *item_list = childGetListInterface("item_list"); + LLScrollListCtrl* item_list = getChild("item_list"); if (!item_list) { removeVOInventoryListener(); return; } + item_list->deleteAllItems(); + + if (!inv) + { + llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged" + << llendl; + + return; + } + // default to turning off the buy button. - childDisable("buy_btn"); + LLView* buy_btn = getChildView("buy_btn"); + buy_btn->setEnabled(FALSE); LLUUID owner_id; BOOL is_group_owned; @@ -214,13 +221,15 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, // There will be at least one item shown in the display, so go // ahead and enable the buy button. - childEnable("buy_btn"); + buy_btn->setEnabled(TRUE); // Create the line in the list LLSD row; BOOL item_is_multi = FALSE; - if ( inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED ) + if ((inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_LANDMARK_VISITED + || inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS) + && !(inv_item->getFlags() & LLInventoryItemFlags::II_FLAGS_WEARABLES_MASK)) { item_is_multi = TRUE; } @@ -260,28 +269,25 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj, if (wearable_count > 0) { - childEnable("wear_check"); - childSetValue("wear_check", LLSD(false) ); + getChildView("wear_check")->setEnabled(TRUE); + getChild("wear_check")->setValue(LLSD(false) ); } - - removeVOInventoryListener(); } -// static -void LLFloaterBuyContents::onClickBuy(void*) +void LLFloaterBuyContents::onClickBuy() { // Make sure this wasn't selected through other mechanisms // (ie, being the default button and pressing enter. - if(!sInstance->childIsEnabled("buy_btn")) + if(!getChildView("buy_btn")->getEnabled()) { // We shouldn't be enabled. Just close. - sInstance->close(); + close(); return; } // We may want to wear this item - if (sInstance->childGetValue("wear_check")) + if (getChild("wear_check")->getValue()) { LLInventoryState::sWearNewClothing = TRUE; } @@ -293,14 +299,14 @@ void LLFloaterBuyContents::onClickBuy(void*) // *NOTE: doesn't work for multiple object buy, which UI does not // currently support sale info is used for verification only, if // it doesn't match region info then sale is canceled. - LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, sInstance->mSaleInfo); + LLSelectMgr::getInstance()->sendBuy(gAgent.getID(), category_id, mSaleInfo); - sInstance->close(); + close(); } // static -void LLFloaterBuyContents::onClickCancel(void*) +void LLFloaterBuyContents::onClickCancel() { - sInstance->close(); + close(); } diff --git a/indra/newview/llfloaterbuycontents.h b/indra/newview/llfloaterbuycontents.h index 63e62ea83..d30adcb06 100644 --- a/indra/newview/llfloaterbuycontents.h +++ b/indra/newview/llfloaterbuycontents.h @@ -47,27 +47,26 @@ class LLViewerObject; class LLObjectSelection; class LLFloaterBuyContents -: public LLFloater, public LLVOInventoryListener +: public LLFloater, public LLVOInventoryListener, public LLSingleton { public: static void show(const LLSaleInfo& sale_info); -protected: LLFloaterBuyContents(); ~LLFloaterBuyContents(); - + /*virtual*/ BOOL postBuild(); + +protected: void requestObjectInventories(); /*virtual*/ void inventoryChanged(LLViewerObject* obj, LLInventoryObject::object_list_t* inv, S32 serial_num, void* data); - - static void onClickBuy(void*); - static void onClickCancel(void*); + + void onClickBuy(); + void onClickCancel(); protected: - static LLFloaterBuyContents* sInstance; - LLSafeHandle mObjectSelection; LLSaleInfo mSaleInfo; }; From 8ec5915b7c768451094b74803b73eae535beaea9 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Tue, 12 Feb 2013 20:49:39 -0600 Subject: [PATCH 14/18] Removed some logic in llfloateravatarlist that shouldn't have been there. --- indra/newview/llfloateravatarlist.cpp | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/indra/newview/llfloateravatarlist.cpp b/indra/newview/llfloateravatarlist.cpp index 92a80a517..f410bd615 100644 --- a/indra/newview/llfloateravatarlist.cpp +++ b/indra/newview/llfloateravatarlist.cpp @@ -500,18 +500,9 @@ void LLFloaterAvatarList::assessColumns() if(!client_hidden) { - name_col->setWidth(width_name); + name_col->setWidth(llmax(width_name.get(),10)); } } - else if (!hide_client) - { - mAvatarList->getColumn(LIST_CLIENT)->setWidth(0); - mAvatarList->getColumn(LIST_AVATAR_NAME)->setWidth(0); - mAvatarList->getColumn(LIST_AVATAR_NAME)->mDynamicWidth = FALSE; - mAvatarList->getColumn(LIST_AVATAR_NAME)->mRelWidth = 0; - mAvatarList->getColumn(LIST_CLIENT)->mDynamicWidth = TRUE; - mAvatarList->getColumn(LIST_CLIENT)->mRelWidth = -1; - } mAvatarList->updateLayout(); } From 2f5ab6f8e8f8697951314ba6875bbc05010860d7 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Wed, 13 Feb 2013 16:31:16 -0600 Subject: [PATCH 15/18] Once more, with feeling. (currency transaction messages) --- indra/newview/llviewermessage.cpp | 67 ++++++++++++------- .../skins/default/xui/en-us/strings.xml | 22 +++--- 2 files changed, 52 insertions(+), 37 deletions(-) diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index eabb0a7c5..c758d8909 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5799,17 +5799,34 @@ static std::string reason_from_transaction_type(S32 transaction_type, } } -static void process_money_group_name_reply(const std::string& name, const std::string notification, LLSD args, LLSD payload) +static void money_balance_group_notify(const LLUUID& group_id, + const std::string& name, + bool is_group, + std::string message, + std::string notification, + LLStringUtil::format_map_t args, + LLSD payload) { args["NAME"] = name; - LLNotificationsUtil::add(notification,args,payload); + LLSD msg_args; + msg_args["MESSAGE"] = LLTrans::getString(message,args); + LLNotificationsUtil::add(notification,msg_args,payload); } -static void process_money_avatar_name_reply(const LLAvatarName& name, const std::string notification, LLSD args, LLSD payload) + +static void money_balance_avatar_notify(const LLUUID& agent_id, + const LLAvatarName& av_name, + std::string message, + std::string notification, + LLStringUtil::format_map_t args, + LLSD payload) { - std::string av_name; - LLAvatarNameCache::getPNSName(name,av_name); - args["NAME"] = av_name; - LLNotificationsUtil::add(notification,args,payload); + + std::string name; + LLAvatarNameCache::getPNSName(av_name,name); + args["NAME"] = name; + LLSD msg_args; + msg_args["MESSAGE"] = LLTrans::getString(message,args); + LLNotificationsUtil::add(notification,msg_args,payload); } static void process_money_balance_reply_extended(LLMessageSystem* msg) { @@ -5857,7 +5874,6 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) std::string message; static LLCachedControl no_transaction_clutter("LiruNoTransactionClutter", false); std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; - LLSD final_args; LLSD payload; bool you_paid_someone = (source_id == gAgentID); @@ -5869,31 +5885,30 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) { if (dest_id.notNull()) { - message = success ? LLTrans::getString("you_paid_ldollars", args) : - LLTrans::getString("you_paid_failure_ldollars", args); + message = success ? "you_paid_ldollars" : + "you_paid_failure_ldollars"; } else { // transaction fee to the system, eg, to create a group - message = success ? LLTrans::getString("you_paid_ldollars_no_name", args) : - LLTrans::getString("you_paid_failure_ldollars_no_name", args); + message = success ? "you_paid_ldollars_no_name" : + "you_paid_failure_ldollars_no_name"; } } else { if (dest_id.notNull()) { - message = success ? LLTrans::getString("you_paid_ldollars_no_reason", args) : - LLTrans::getString("you_paid_failure_ldollars_no_reason", args); + message = success ? "you_paid_ldollars_no_reason" : + "you_paid_failure_ldollars_no_reason"; } else { // no target, no reason, you just paid money - message = success ? LLTrans::getString("you_paid_ldollars_no_info", args) : - LLTrans::getString("you_paid_failure_ldollars_no_info", args); + message = success ? "you_paid_ldollars_no_info" : + "you_paid_failure_ldollars_no_info"; } } - final_args["MESSAGE"] = message; } else { @@ -5902,13 +5917,12 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) name_id = source_id; if (!reason.empty()) { - message = LLTrans::getString("paid_you_ldollars", args); + message = "paid_you_ldollars"; } else { - message = LLTrans::getString("paid_you_ldollars_no_reason", args); + message = "paid_you_ldollars_no_reason"; } - final_args["MESSAGE"] = message; // make notification loggable payload["from_id"] = source_id; @@ -5920,14 +5934,15 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg) if (is_name_group) { gCacheName->getGroup(name_id, - boost::bind(&process_money_group_name_reply, - _2, notification, final_args, payload)); + boost::bind(&money_balance_group_notify, + _1, _2, _3, message, + notification, args, payload)); } - else - { + else { LLAvatarNameCache::get(name_id, - boost::bind(&process_money_avatar_name_reply, - _2, notification, final_args, payload)); + boost::bind(&money_balance_avatar_notify, + _1, _2, message, + notification, args, payload)); } } diff --git a/indra/newview/skins/default/xui/en-us/strings.xml b/indra/newview/skins/default/xui/en-us/strings.xml index a87d876e9..3421f2c1a 100644 --- a/indra/newview/skins/default/xui/en-us/strings.xml +++ b/indra/newview/skins/default/xui/en-us/strings.xml @@ -1908,7 +1908,7 @@ Requests that a nonphysical object be keyframed according to keyframe list. key llTransferLindenDollars(key destination, integer amount) -Transfer amount of linden dollars (L$) from script owner to destination. Returns a key to a corresponding transaction_result event for the success of the transfer. +Transfer amount of linden dollars ([CURRENCY]) from script owner to destination. Returns a key to a corresponding transaction_result event for the success of the transfer. string llGetParcelMusicURL() @@ -4005,16 +4005,16 @@ If you continue to receive this message, contact the [SUPPORT_SITE]. Home position set. - [NAME] paid you L$[AMOUNT] [REASON]. - [NAME] paid you L$[AMOUNT]. - You paid [NAME] L$[AMOUNT] [REASON]. - You paid L$[AMOUNT]. - You paid [NAME] L$[AMOUNT]. - You paid L$[AMOUNT] [REASON]. - You failed to pay [NAME] L$[AMOUNT] [REASON]. - You failed to pay L$[AMOUNT]. - You failed to pay [NAME] L$[AMOUNT]. - You failed to pay L$[AMOUNT] [REASON]. + [NAME] paid you [CURRENCY][AMOUNT] [REASON]. + [NAME] paid you [CURRENCY][AMOUNT]. + You paid [NAME] [CURRENCY][AMOUNT] [REASON]. + You paid [CURRENCY][AMOUNT]. + You paid [NAME] [CURRENCY][AMOUNT]. + You paid [CURRENCY][AMOUNT] [REASON]. + You failed to pay [NAME] [CURRENCY][AMOUNT] [REASON]. + You failed to pay [CURRENCY][AMOUNT]. + You failed to pay [NAME] [CURRENCY][AMOUNT]. + You failed to pay [CURRENCY][AMOUNT] [REASON]. for [ITEM] for a parcel of land for a land access pass From 51cbb8d6bde814855ba54a630b2e644e8abfb0d8 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Thu, 14 Feb 2013 17:45:10 -0600 Subject: [PATCH 16/18] Catch up with LL regarding viewer stat recording. --- indra/llcommon/llstatenums.h | 7 + indra/newview/llappviewer.cpp | 5 +- indra/newview/llfloaterstats.cpp | 65 +++ indra/newview/lltexturefetch.cpp | 661 ++---------------------- indra/newview/lltexturefetch.h | 79 +-- indra/newview/llviewermessage.cpp | 12 + indra/newview/llviewerobjectlist.cpp | 49 +- indra/newview/llviewerobjectlist.h | 2 + indra/newview/llviewerregion.cpp | 7 +- indra/newview/llviewerstats.cpp | 129 +++-- indra/newview/llviewerstats.h | 145 +++--- indra/newview/llviewerstatsrecorder.cpp | 181 ++++--- indra/newview/llviewerstatsrecorder.h | 82 ++- indra/newview/llviewertexturelist.cpp | 8 - indra/newview/llviewerwindow.cpp | 13 +- 15 files changed, 475 insertions(+), 970 deletions(-) diff --git a/indra/llcommon/llstatenums.h b/indra/llcommon/llstatenums.h index 608ac5473..81c4085d1 100644 --- a/indra/llcommon/llstatenums.h +++ b/indra/llcommon/llstatenums.h @@ -63,6 +63,13 @@ enum LL_SIM_STAT_SIMSPARETIME = 32, LL_SIM_STAT_SIMSLEEPTIME = 33, LL_SIM_STAT_IOPUMPTIME = 34, + LL_SIM_STAT_PCTSCRIPTSRUN = 35, + LL_SIM_STAT_REGION_IDLE = 36, // dataserver only + LL_SIM_STAT_REGION_IDLE_POSSIBLE = 37, // dataserver only + LL_SIM_STAT_SIMAISTEPTIMEMS = 38, + LL_SIM_STAT_SKIPPEDAISILSTEPS_PS = 39, + LL_SIM_STAT_PCTSTEPPEDCHARACTERS = 40 + }; #endif diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp index 76ba4b9cb..dd7255e21 100644 --- a/indra/newview/llappviewer.cpp +++ b/indra/newview/llappviewer.cpp @@ -690,9 +690,6 @@ bool LLAppViewer::init() ////////////////////////////////////////////////////////////////////////////// // *FIX: The following code isn't grouped into functions yet. - // Statistics / debug timer initialization - init_statistics(); - // // Various introspection concerning the libs we're using - particularly // the libs involved in getting to a full login screen. @@ -3969,7 +3966,7 @@ void LLAppViewer::idle() idle_afk_check(); // Update statistics for this frame - update_statistics(gFrameCount); + update_statistics(); } //////////////////////////////////////// diff --git a/indra/newview/llfloaterstats.cpp b/indra/newview/llfloaterstats.cpp index fb9b1cc24..a60619882 100644 --- a/indra/newview/llfloaterstats.cpp +++ b/indra/newview/llfloaterstats.cpp @@ -45,6 +45,7 @@ #include "pipeline.h" #include "llviewerobjectlist.h" #include "llviewertexturelist.h" +#include "lltexturefetch.h" #include "sgmemstat.h" const S32 LL_SCROLL_BORDER = 1; @@ -151,10 +152,36 @@ void LLFloaterStats::buildStats() stat_barp->mLabelSpacing = 500.f; stat_barp->mPerSec = TRUE; + stat_barp = render_statviewp->addStat("Object Cache Hit Rate", &(LLViewerStats::getInstance()->mNumNewObjectsStat), std::string(), false, true); + stat_barp->setLabel("Object Cache Hit Rate"); + stat_barp->setUnitLabel("%"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 100.f; + stat_barp->mTickSpacing = 20.f; + stat_barp->mLabelSpacing = 20.f; + stat_barp->mPerSec = FALSE; // Texture statistics LLStatView *texture_statviewp = render_statviewp->addStatView("texture stat view", "Texture", "OpenDebugStatTexture", rect); + stat_barp = texture_statviewp->addStat("Cache Hit Rate", &(LLTextureFetch::sCacheHitRate), std::string(), false, true); + stat_barp->setLabel("Cache Hit Rate"); + stat_barp->setUnitLabel("%"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 100.f; + stat_barp->mTickSpacing = 20.f; + stat_barp->mLabelSpacing = 20.f; + stat_barp->mPerSec = FALSE; + + stat_barp = texture_statviewp->addStat("Cache Read Latency", &(LLTextureFetch::sCacheReadLatency), std::string(), false, true); + stat_barp->setUnitLabel("msec"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 1000.f; + stat_barp->mTickSpacing = 100.f; + stat_barp->mLabelSpacing = 200.f; + stat_barp->mPerSec = FALSE; + stat_barp->mDisplayMean = FALSE; + stat_barp = texture_statviewp->addStat("Count", &(LLViewerStats::getInstance()->mNumImagesStat), "DebugStatModeTextureCount"); stat_barp->setUnitLabel(""); stat_barp->mMinBar = 0.f; @@ -365,6 +392,15 @@ void LLFloaterStats::buildStats() stat_barp->mPerSec = FALSE; stat_barp->mDisplayMean = FALSE; + stat_barp = sim_statviewp->addStat("Scripts Run", &(LLViewerStats::getInstance()->mSimPctScriptsRun), std::string(), false, true); + stat_barp->setUnitLabel("%"); + stat_barp->mPrecision = 3; + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 100.f; + stat_barp->mTickSpacing = 10.f; + stat_barp->mLabelSpacing = 20.f; + stat_barp->mPerSec = FALSE; + stat_barp = sim_statviewp->addStat("Script Events", &(LLViewerStats::getInstance()->mSimScriptEPS), "DebugStatModeSimScriptEvents"); stat_barp->setUnitLabel(" eps"); stat_barp->mPrecision = 0; @@ -375,6 +411,35 @@ void LLFloaterStats::buildStats() stat_barp->mPerSec = FALSE; stat_barp->mDisplayMean = FALSE; + LLStatView *pathfinding_viewp = sim_statviewp->addStatView("pathfinding view", "Pathfinding Details", std::string(), rect); + stat_barp = pathfinding_viewp->addStat("AI Step Time", &(LLViewerStats::getInstance()->mSimSimAIStepMsec)); + stat_barp->setUnitLabel("ms"); + stat_barp->mPrecision = 3; + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 40.f; + stat_barp->mTickSpacing = 10.f; + stat_barp->mLabelSpacing = 20.f; + stat_barp->mPerSec = FALSE; + stat_barp->mDisplayMean = FALSE; + + stat_barp = render_statviewp->addStat("Skipped Silhouette Steps", &(LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps)); + stat_barp->setUnitLabel("/sec"); + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 45.f; + stat_barp->mTickSpacing = 4.f; + stat_barp->mLabelSpacing = 8.f; + stat_barp->mPrecision = 0; + + stat_barp = pathfinding_viewp->addStat("Characters Updated", &(LLViewerStats::getInstance()->mSimSimPctSteppedCharacters)); + stat_barp->setUnitLabel("%"); + stat_barp->mPrecision = 1; + stat_barp->mMinBar = 0.f; + stat_barp->mMaxBar = 100.f; + stat_barp->mTickSpacing = 10.f; + stat_barp->mLabelSpacing = 20.f; + stat_barp->mPerSec = FALSE; + stat_barp->mDisplayMean = TRUE; + stat_barp = sim_statviewp->addStat("Packets In", &(LLViewerStats::getInstance()->mSimInPPS), "DebugStatModeSimInPPS"); stat_barp->setUnitLabel(" pps"); stat_barp->mPrecision = 0; diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp index 276bc4a0a..accd96b42 100644 --- a/indra/newview/lltexturefetch.cpp +++ b/indra/newview/lltexturefetch.cpp @@ -53,6 +53,7 @@ #include "llviewertexture.h" #include "llviewerregion.h" #include "llviewerstats.h" +#include "llviewerstatsrecorder.h" #include "llworld.h" #include "llstartup.h" #include "llbuffer.h" @@ -61,6 +62,9 @@ class AIHTTPTimeoutPolicy; extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout; extern AIHTTPTimeoutPolicy lcl_responder_timeout; +LLStat LLTextureFetch::sCacheHitRate("texture_cache_hits", 128); +LLStat LLTextureFetch::sCacheReadLatency("texture_cache_read_latency", 128); + ////////////////////////////////////////////////////////////////////////////// class LLTextureFetchWorker : public LLWorkerClass { @@ -250,6 +254,8 @@ private: S32 mDecodedDiscard; LLFrameTimer mRequestedTimer; LLFrameTimer mFetchTimer; + LLTimer mCacheReadTimer; + F32 mCacheReadTime; LLTextureCache::handle_t mCacheReadHandle; LLTextureCache::handle_t mCacheWriteHandle; std::vector mHttpBuffer; @@ -289,9 +295,6 @@ private: S32 mLastPacket; U16 mTotalPackets; U8 mImageCodec; -#if HTTP_METRICS - LLViewerAssetStats::duration_t mMetricsStartTime; -#endif }; ////////////////////////////////////////////////////////////////////////////// @@ -384,20 +387,6 @@ public: } mFetcher->removeFromHTTPQueue(mID, data_size); - -#if HTTP_METRICS - if (worker->mMetricsStartTime) - { - LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, - true, - LLImageBase::TYPE_AVATAR_BAKE == worker->mType, - LLViewerAssetStatsFF::get_timestamp() - worker->mMetricsStartTime); - worker->mMetricsStartTime = 0; - } - LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, - true, - LLImageBase::TYPE_AVATAR_BAKE == worker->mType); -#endif } else { @@ -514,230 +503,6 @@ static bool sgConnectionThrottle() { } #endif -#if HTTP_METRICS -// Cross-thread messaging for asset metrics. - -/** - * @brief Base class for cross-thread requests made of the fetcher - * - * I believe the intent of the LLQueuedThread class was to - * have these operations derived from LLQueuedThread::QueuedRequest - * but the texture fetcher has elected to manage the queue - * in its own manner. So these are free-standing objects which are - * managed in simple FIFO order on the mCommands queue of the - * LLTextureFetch object. - * - * What each represents is a simple command sent from an - * outside thread into the TextureFetch thread to be processed - * in order and in a timely fashion (though not an absolute - * higher priority than other operations of the thread). - * Each operation derives a new class from the base customizing - * members, constructors and the doWork() method to effect - * the command. - * - * The flow is one-directional. There are two global instances - * of the LLViewerAssetStats collector, one for the main program's - * thread pointed to by gViewerAssetStatsMain and one for the - * TextureFetch thread pointed to by gViewerAssetStatsThread1. - * Common operations has each thread recording metrics events - * into the respective collector unconcerned with locking and - * the state of any other thread. But when the agent moves into - * a different region or the metrics timer expires and a report - * needs to be sent back to the grid, messaging across threads - * is required to distribute data and perform global actions. - * In pseudo-UML, it looks like: - * - * Main Thread1 - * . . - * . . - * +-----+ . - * | AM | . - * +--+--+ . - * +-------+ | . - * | Main | +--+--+ . - * | | | SRE |---. . - * | Stats | +-----+ \ . - * | | | \ (uuid) +-----+ - * | Coll. | +--+--+ `-------->| SR | - * +-------+ | MSC | +--+--+ - * | ^ +-----+ | - * | | (uuid) / . +-----+ (uuid) - * | `--------' . | MSC |---------. - * | . +-----+ | - * | +-----+ . v - * | | TE | . +-------+ - * | +--+--+ . | Thd1 | - * | | . | | - * | +-----+ . | Stats | - * `--------->| RSC | . | | - * +--+--+ . | Coll. | - * | . +-------+ - * +--+--+ . | - * | SME |---. . | - * +-----+ \ . | - * . \ (clone) +-----+ | - * . `-------->| SM | | - * . +--+--+ | - * . | | - * . +-----+ | - * . | RSC |<--------' - * . +-----+ - * . | - * . +-----+ - * . | CP |--> HTTP POST - * . +-----+ - * . . - * . . - * - * - * Key: - * - * SRE - Set Region Enqueued. Enqueue a 'Set Region' command in - * the other thread providing the new UUID of the region. - * TFReqSetRegion carries the data. - * SR - Set Region. New region UUID is sent to the thread-local - * collector. - * SME - Send Metrics Enqueued. Enqueue a 'Send Metrics' command - * including an ownership transfer of a cloned LLViewerAssetStats. - * TFReqSendMetrics carries the data. - * SM - Send Metrics. Global metrics reporting operation. Takes - * the cloned stats from the command, merges it with the - * thread's local stats, converts to LLSD and sends it on - * to the grid. - * AM - Agent Moved. Agent has completed some sort of move to a - * new region. - * TE - Timer Expired. Metrics timer has expired (on the order - * of 10 minutes). - * CP - CURL Post - * MSC - Modify Stats Collector. State change in the thread-local - * collector. Typically a region change which affects the - * global pointers used to find the 'current stats'. - * RSC - Read Stats Collector. Extract collector data cloning it - * (i.e. deep copy) when necessary. - * - */ -class LLTextureFetch::TFRequest // : public LLQueuedThread::QueuedRequest -{ -public: - // Default ctors and assignment operator are correct. - - virtual ~TFRequest() - {} - - // Patterned after QueuedRequest's method but expected behavior - // is different. Always expected to complete on the first call - // and work dispatcher will assume the same and delete the - // request after invocation. - virtual bool doWork(LLTextureFetch * fetcher) = 0; -}; - -namespace -{ - -/** - * @brief Implements a 'Set Region' cross-thread command. - * - * When an agent moves to a new region, subsequent metrics need - * to be binned into a new or existing stats collection in 1:1 - * relationship with the region. We communicate this region - * change across the threads involved in the communication with - * this message. - * - * Corresponds to LLTextureFetch::commandSetRegion() - */ -class TFReqSetRegion : public LLTextureFetch::TFRequest -{ -public: - TFReqSetRegion(U64 region_handle) - : LLTextureFetch::TFRequest(), - mRegionHandle(region_handle) - {} - TFReqSetRegion & operator=(const TFReqSetRegion &); // Not defined - - virtual ~TFReqSetRegion() - {} - - virtual bool doWork(LLTextureFetch * fetcher); - -public: - const U64 mRegionHandle; -}; - - -/** - * @brief Implements a 'Send Metrics' cross-thread command. - * - * This is the big operation. The main thread gathers metrics - * for a period of minutes into LLViewerAssetStats and other - * objects then makes a snapshot of the data by cloning the - * collector. This command transfers the clone, along with a few - * additional arguments (UUIDs), handing ownership to the - * TextureFetch thread. It then merges its own data into the - * cloned copy, converts to LLSD and kicks off an HTTP POST of - * the resulting data to the currently active metrics collector. - * - * Corresponds to LLTextureFetch::commandSendMetrics() - */ - -class TFReqSendMetrics : public LLTextureFetch::TFRequest -{ -public: - /** - * Construct the 'Send Metrics' command to have the TextureFetch - * thread add and log metrics data. - * - * @param caps_url URL of a "ViewerMetrics" Caps target - * to receive the data. Does not have to - * be associated with a particular region. - * - * @param session_id UUID of the agent's session. - * - * @param agent_id UUID of the agent. (Being pure here...) - * - * @param main_stats Pointer to a clone of the main thread's - * LLViewerAssetStats data. Thread1 takes - * ownership of the copy and disposes of it - * when done. - */ - - TFReqSendMetrics(const std::string & caps_url, - const LLUUID & session_id, - const LLUUID & agent_id, - LLViewerAssetStats * main_stats) - : LLTextureFetch::TFRequest(), - mCapsURL(caps_url), - mSessionID(session_id), - mAgentID(agent_id), - mMainStats(main_stats) - {} - TFReqSendMetrics & operator=(const TFReqSendMetrics &); // Not defined - - virtual ~TFReqSendMetrics(); - - virtual bool doWork(LLTextureFetch * fetcher); - -public: - const std::string mCapsURL; - const LLUUID mSessionID; - const LLUUID mAgentID; - LLViewerAssetStats * mMainStats; -}; - -/* - * Examines the merged viewer metrics report and if found to be too long, - * will attempt to truncate it in some reasonable fashion. - * - * @param max_regions Limit of regions allowed in report. - * - * @param metrics Full, merged viewer metrics report. - * - * @returns If data was truncated, returns true. - */ -bool truncate_viewer_metrics(int max_regions, LLSD & metrics); - -} // end of anonymous namespace -#endif - ////////////////////////////////////////////////////////////////////////////// //static @@ -757,11 +522,6 @@ const char* LLTextureFetchWorker::sStateDescs[] = { "DONE", }; -#if HTTP_METRICS -// static -volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data break -#endif - // called from MAIN THREAD LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, @@ -786,6 +546,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mRequestedDiscard(-1), mLoadedDiscard(-1), mDecodedDiscard(-1), + mCacheReadTime(0.f), mCacheReadHandle(LLTextureCache::nullHandle()), mCacheWriteHandle(LLTextureCache::nullHandle()), mRequestedSize(0), @@ -810,9 +571,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, mLastPacket(-1), mTotalPackets(0), mImageCodec(IMG_CODEC_INVALID) -#if HTTP_METRICS - ,mMetricsStartTime(0) -#endif { mCanUseNET = mUrl.empty() ; @@ -1064,6 +822,7 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } else if (mUrl.empty()) { @@ -1072,8 +831,9 @@ bool LLTextureFetchWorker::doWork(S32 param) CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, offset, size, responder); + mCacheReadTimer.reset(); } - else if(mCanUseHTTP) + else if(!mUrl.empty() && mCanUseHTTP) { if (!(mUrl.compare(0, 7, "http://") == 0)) { @@ -1101,6 +861,9 @@ bool LLTextureFetchWorker::doWork(S32 param) } else { + // + //This should never happen + // return false; } } @@ -1124,7 +887,7 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; - // fall through + LLTextureFetch::sCacheHitRate.addValue(100.f); } else { @@ -1139,7 +902,9 @@ bool LLTextureFetchWorker::doWork(S32 param) LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; mState = LOAD_FROM_NETWORK; } + // fall through + LLTextureFetch::sCacheHitRate.addValue(0.f); } } @@ -1198,15 +963,6 @@ bool LLTextureFetchWorker::doWork(S32 param) mRequestedDiscard = mDesiredDiscard; mSentRequest = QUEUED; mFetcher->addToNetworkQueue(this); -#if HTTP_METRICS - if (! mMetricsStartTime) - { - mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); - } - LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, - false, - LLImageBase::TYPE_AVATAR_BAKE == mType); -#endif setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; @@ -1217,12 +973,6 @@ bool LLTextureFetchWorker::doWork(S32 param) //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); // Make certain this is in the network queue //mFetcher->addToNetworkQueue(this); - //if (! mMetricsStartTime) - //{ - // mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); - //} - //LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, false, - // LLImageBase::TYPE_AVATAR_BAKE == mType); //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return false; } @@ -1247,33 +997,10 @@ bool LLTextureFetchWorker::doWork(S32 param) setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); mState = DECODE_IMAGE; mWriteToCacheState = SHOULD_WRITE; - -#if HTTP_METRICS - if (mMetricsStartTime) - { - LLViewerAssetStatsFF::record_response_thread1(LLViewerAssetType::AT_TEXTURE, - false, - LLImageBase::TYPE_AVATAR_BAKE == mType, - LLViewerAssetStatsFF::get_timestamp() - mMetricsStartTime); - mMetricsStartTime = 0; - } - LLViewerAssetStatsFF::record_dequeue_thread1(LLViewerAssetType::AT_TEXTURE, - false, - LLImageBase::TYPE_AVATAR_BAKE == mType); -#endif } else { mFetcher->addToNetworkQueue(this); // failsafe -#if HTTP_METRICS - if (! mMetricsStartTime) - { - mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); - } - LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, - false, - LLImageBase::TYPE_AVATAR_BAKE == mType); -#endif setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); } return false; @@ -1340,15 +1067,6 @@ bool LLTextureFetchWorker::doWork(S32 param) mState = WAIT_HTTP_REQ; mFetcher->addToHTTPQueue(mID); -#if HTTP_METRICS - if (! mMetricsStartTime) - { - mMetricsStartTime = LLViewerAssetStatsFF::get_timestamp(); - } - LLViewerAssetStatsFF::record_enqueue_thread1(LLViewerAssetType::AT_TEXTURE, - true, - LLImageBase::TYPE_AVATAR_BAKE == mType); -#endif if(mRequestedOffset>0) { @@ -1573,11 +1291,12 @@ bool LLTextureFetchWorker::doWork(S32 param) if (mState == DECODE_IMAGE) { static LLCachedControl textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); - if(textures_decode_disabled) + + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it + if (textures_decode_disabled) { // for debug use, don't decode mState = DONE; - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return true; } @@ -1585,7 +1304,6 @@ bool LLTextureFetchWorker::doWork(S32 param) { // We aborted, don't decode mState = DONE; - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return true; } @@ -1595,7 +1313,6 @@ bool LLTextureFetchWorker::doWork(S32 param) //abort, don't decode mState = DONE; - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return true; } if (mLoadedDiscard < 0) @@ -1604,10 +1321,9 @@ bool LLTextureFetchWorker::doWork(S32 param) //abort, don't decode mState = DONE; - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); return true; } - setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it + mRawImage = NULL; mAuxImage = NULL; llassert_always(mFormattedImage.notNull()); @@ -1899,6 +1615,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL; if (data_size > 0) { + LLViewerStatsRecorder::instance().textureFetch(data_size); // *TODO: set the formatted image data here directly to avoid the copy llassert(mHttpBuffer.empty()); mHttpBuffer.resize(data_size); @@ -1932,6 +1649,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels, mLoaded = TRUE; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + LLViewerStatsRecorder::instance().log(0.2f); return data_size ; } @@ -2017,6 +1735,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag mDecoded = TRUE; // llinfos << mID << " : DECODE COMPLETE " << llendl; setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mCacheReadTime = mCacheReadTimer.getElapsedTimeF32(); } ////////////////////////////////////////////////////////////////////////////// @@ -2058,13 +1777,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image mTextureBandwidth(0), mHTTPTextureBits(0), mTotalHTTPRequests(0) -#if HTTP_METRICS - ,mQAMode(qa_mode) -#endif { -#if HTTP_METRICS - mCurlPOSTRequestCount = 0; -#endif mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold")); } @@ -2072,14 +1785,6 @@ LLTextureFetch::~LLTextureFetch() { clearDeleteList() ; -#if HTTP_METRICS - while (! mCommands.empty()) - { - TFRequest * req(mCommands.front()); - mCommands.erase(mCommands.begin()); - delete req; - } -#endif // ~LLQueuedThread() called here } @@ -2341,6 +2046,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, discard_level = worker->mDecodedDiscard; raw = worker->mRawImage; aux = worker->mAuxImage; + F32 cache_read_time = worker->mCacheReadTime; + if (cache_read_time != 0.f) + { + sCacheReadLatency.addValue(cache_read_time * 1000.f); + } res = true; LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; worker->unlockWorkMutex(); @@ -2393,10 +2103,6 @@ S32 LLTextureFetch::getPending() LLMutexLock lock(&mQueueMutex); res = mRequestQueue.size(); -#if HTTP_METRICS - res += mCurlPOSTRequestCount; - res += mCommands.size(); -#endif } unlockData(); return res; @@ -2414,22 +2120,7 @@ bool LLTextureFetch::runCondition() // // Changes here may need to be reflected in getPending(). -#if HTTP_METRICS - bool have_no_commands(false); - { - LLMutexLock lock(&mQueueMutex); - - have_no_commands = mCommands.empty(); - } - - bool have_no_curl_requests(0 == mCurlPOSTRequestCount); - - return ! (have_no_commands - && have_no_curl_requests - && (mRequestQueue.empty() && mIdleThread)); // From base class -#else - return !(mRequestQueue.empty() && mIdleThread); -#endif + return ! (mRequestQueue.empty() && mIdleThread); // From base class } ////////////////////////////////////////////////////////////////////////////// @@ -2437,10 +2128,6 @@ bool LLTextureFetch::runCondition() // MAIN THREAD (unthreaded envs), WORKER THREAD (threaded envs) void LLTextureFetch::commonUpdate() { -#if HTTP_METRICS - // Run a cross-thread command, if any. - cmdDoWork(); -#endif } @@ -2799,11 +2486,16 @@ bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 mNetworkQueueMutex.unlock() ; return false; } + + LLViewerStatsRecorder::instance().textureFetch(data_size); + LLViewerStatsRecorder::instance().log(0.1f); + worker->lockWorkMutex(); - // Copy header data into image object - worker->mImageCodec = codec; - worker->mTotalPackets = packets; + + // Copy header data into image object + worker->mImageCodec = codec; + worker->mTotalPackets = packets; worker->mFileSize = (S32)totalbytes; llassert_always(totalbytes > 0); llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); @@ -2844,8 +2536,12 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1 mNetworkQueueMutex.unlock() ; return false; } + + LLViewerStatsRecorder::instance().textureFetch(data_size); + LLViewerStatsRecorder::instance().log(0.1f); worker->lockWorkMutex(); + res = worker->insertPacket(packet_num, data, data_size); @@ -2959,277 +2655,12 @@ void LLTextureFetch::dump() << " STATE: " << worker->sStateDescs[worker->mState] << llendl; } -} -////////////////////////////////////////////////////////////////////////////// - -// cross-thread command methods - -#if HTTP_METRICS -void LLTextureFetch::commandSetRegion(U64 region_handle) -{ - TFReqSetRegion * req = new TFReqSetRegion(region_handle); - - cmdEnqueue(req); -} - -void LLTextureFetch::commandSendMetrics(const std::string & caps_url, - const LLUUID & session_id, - const LLUUID & agent_id, - LLViewerAssetStats * main_stats) -{ - TFReqSendMetrics * req = new TFReqSendMetrics(caps_url, session_id, agent_id, main_stats); - - cmdEnqueue(req); -} - -void LLTextureFetch::commandDataBreak() -{ - // The pedantically correct way to implement this is to create a command - // request object in the above fashion and enqueue it. However, this is - // simple data of an advisorial not operational nature and this case - // of shared-write access is tolerable. - - LLTextureFetch::svMetricsDataBreak = true; -} - -void LLTextureFetch::cmdEnqueue(TFRequest * req) -{ - lockQueue(); - mCommands.push_back(req); - unlockQueue(); - - unpause(); -} - -LLTextureFetch::TFRequest * LLTextureFetch::cmdDequeue() -{ - TFRequest * ret = 0; - - lockQueue(); - if (! mCommands.empty()) + llinfos << "LLTextureFetch ACTIVE_HTTP:" << llendl; + for (queue_t::const_iterator iter(mHTTPTextureQueue.begin()); + mHTTPTextureQueue.end() != iter; + ++iter) { - ret = mCommands.front(); - mCommands.erase(mCommands.begin()); - } - unlockQueue(); - - return ret; -} - -void LLTextureFetch::cmdDoWork() -{ - if (mDebugPause) - { - return; // debug: don't do any work - } - - TFRequest * req = cmdDequeue(); - if (req) - { - // One request per pass should really be enough for this. - req->doWork(this); - delete req; + llinfos << " ID: " << (*iter) << llendl; } } - - -////////////////////////////////////////////////////////////////////////////// - -// Private (anonymous) class methods implementing the command scheme. - -namespace -{ - -/** - * Implements the 'Set Region' command. - * - * Thread: Thread1 (TextureFetch) - */ -bool -TFReqSetRegion::doWork(LLTextureFetch *) -{ - LLViewerAssetStatsFF::set_region_thread1(mRegionHandle); - return true; -} - - -TFReqSendMetrics::~TFReqSendMetrics() -{ - delete mMainStats; - mMainStats = 0; -} - - -/** - * Implements the 'Send Metrics' command. Takes over - * ownership of the passed LLViewerAssetStats pointer. - * - * Thread: Thread1 (TextureFetch) - */ -bool -TFReqSendMetrics::doWork(LLTextureFetch * fetcher) -{ - /* - * HTTP POST responder. Doesn't do much but tries to - * detect simple breaks in recording the metrics stream. - * - * The 'volatile' modifiers don't indicate signals, - * mmap'd memory or threads, really. They indicate that - * the referenced data is part of a pseudo-closure for - * this responder rather than being required for correct - * operation. - * - * We don't try very hard with the POST request. We give - * it one shot and that's more-or-less it. With a proper - * refactoring of the LLQueuedThread usage, these POSTs - * could be put in a request object and made more reliable. - */ - class lcl_responder : public LLHTTPClient::ResponderWithResult - { - public: - lcl_responder(LLTextureFetch * fetcher, - S32 expected_sequence, - volatile const S32 & live_sequence, - volatile bool & reporting_break, - volatile bool & reporting_started) - : mFetcher(fetcher), - mExpectedSequence(expected_sequence), - mLiveSequence(live_sequence), - mReportingBreak(reporting_break), - mReportingStarted(reporting_started) - { - mFetcher->incrCurlPOSTCount(); - } - - ~lcl_responder() - { - mFetcher->decrCurlPOSTCount(); - } - - /*virtual*/ void error(U32 status_num, const std::string & reason) - { - if (mLiveSequence == mExpectedSequence) - { - mReportingBreak = true; - } - LL_WARNS("Texture") << "Break in metrics stream due to POST failure to metrics collection service. Reason: " - << reason << LL_ENDL; - } - - /*virtual*/ void result(const LLSD & content) - { - if (mLiveSequence == mExpectedSequence) - { - mReportingBreak = false; - mReportingStarted = true; - } - } - /*virtual*/ AIHTTPTimeoutPolicy const& getHTTPTimeoutPolicy(void) const { return lcl_responder_timeout; } - /*virtual*/ char const* getName(void) const { return "lcl_responder"; } - - private: - LLTextureFetch * mFetcher; - S32 mExpectedSequence; - volatile const S32 & mLiveSequence; - volatile bool & mReportingBreak; - volatile bool & mReportingStarted; - - }; // class lcl_responder - - if (! gViewerAssetStatsThread1) - return true; - - static volatile bool reporting_started(false); - static volatile S32 report_sequence(0); - - // We've taken over ownership of the stats copy at this - // point. Get a working reference to it for merging here - // but leave it in 'this'. Destructor will rid us of it. - LLViewerAssetStats & main_stats = *mMainStats; - - // Merge existing stats into those from main, convert to LLSD - main_stats.merge(*gViewerAssetStatsThread1); - LLSD merged_llsd = main_stats.asLLSD(true); - - // Add some additional meta fields to the content - merged_llsd["session_id"] = mSessionID; - merged_llsd["agent_id"] = mAgentID; - merged_llsd["message"] = "ViewerAssetMetrics"; // Identifies the type of metrics - merged_llsd["sequence"] = report_sequence; // Sequence number - merged_llsd["initial"] = ! reporting_started; // Initial data from viewer - merged_llsd["break"] = LLTextureFetch::svMetricsDataBreak; // Break in data prior to this report - - // Update sequence number - if (S32_MAX == ++report_sequence) - report_sequence = 0; - - // Limit the size of the stats report if necessary. - merged_llsd["truncated"] = truncate_viewer_metrics(10, merged_llsd); - - if (! mCapsURL.empty()) - { - LLHTTPClient::post(mCapsURL, - merged_llsd, - new lcl_responder(fetcher, - report_sequence, - report_sequence, - LLTextureFetch::svMetricsDataBreak, - reporting_started)); - } - else - { - LLTextureFetch::svMetricsDataBreak = true; - } - - // In QA mode, Metrics submode, log the result for ease of testing - if (fetcher->isQAMode()) - { - LL_INFOS("Textures") << merged_llsd << LL_ENDL; - } - - gViewerAssetStatsThread1->reset(); - - return true; -} - -bool -truncate_viewer_metrics(int max_regions, LLSD & metrics) -{ - static const LLSD::String reg_tag("regions"); - static const LLSD::String duration_tag("duration"); - - LLSD & reg_map(metrics[reg_tag]); - if (reg_map.size() <= max_regions) - { - return false; - } - - // Build map of region hashes ordered by duration - typedef std::multimap reg_ordered_list_t; - reg_ordered_list_t regions_by_duration; - - int ind(0); - LLSD::array_const_iterator it_end(reg_map.endArray()); - for (LLSD::array_const_iterator it(reg_map.beginArray()); it_end != it; ++it, ++ind) - { - LLSD::Real duration = (*it)[duration_tag].asReal(); - regions_by_duration.insert(reg_ordered_list_t::value_type(duration, ind)); - } - - // Build a replacement regions array with the longest-persistence regions - LLSD new_region(LLSD::emptyArray()); - reg_ordered_list_t::const_reverse_iterator it2_end(regions_by_duration.rend()); - reg_ordered_list_t::const_reverse_iterator it2(regions_by_duration.rbegin()); - for (int i(0); i < max_regions && it2_end != it2; ++i, ++it2) - { - new_region.append(reg_map[it2->second]); - } - reg_map = new_region; - - return true; -} - -} // end of anonymous namespace -#endif - diff --git a/indra/newview/lltexturefetch.h b/indra/newview/lltexturefetch.h index ac36fe74b..cbf8d1b50 100644 --- a/indra/newview/lltexturefetch.h +++ b/indra/newview/lltexturefetch.h @@ -46,9 +46,6 @@ class HTTPGetResponder; class LLTextureCache; class LLImageDecodeThread; class LLHost; -#if HTTP_METRICS -class LLViewerAssetStats; -#endif // Interface class class LLTextureFetch : public LLWorkerThread @@ -98,22 +95,6 @@ public: LLTextureInfo* getTextureInfo() { return &mTextureInfo; } -#if HTTP_METRICS - // Commands available to other threads to control metrics gathering operations. - void commandSetRegion(U64 region_handle); - void commandSendMetrics(const std::string & caps_url, - const LLUUID & session_id, - const LLUUID & agent_id, - LLViewerAssetStats * main_stats); - void commandDataBreak(); - - bool isQAMode() const { return mQAMode; } - - // Curl POST counter maintenance - inline void incrCurlPOSTCount() { mCurlPOSTRequestCount++; } - inline void decrCurlPOSTCount() { mCurlPOSTRequestCount--; } -#endif - protected: void addToNetworkQueue(LLTextureFetchWorker* worker); void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); @@ -129,37 +110,6 @@ private: /*virtual*/ void threadedUpdate(void); void commonUpdate(); -#if HTTP_METRICS - // Metrics command helpers - /** - * Enqueues a command request at the end of the command queue - * and wakes up the thread as needed. - * - * Takes ownership of the TFRequest object. - * - * Method locks the command queue. - */ - void cmdEnqueue(TFRequest *); - - /** - * Returns the first TFRequest object in the command queue or - * NULL if none is present. - * - * Caller acquires ownership of the object and must dispose of it. - * - * Method locks the command queue. - */ - TFRequest * cmdDequeue(); - - /** - * Processes the first command in the queue disposing of the - * request on completion. Successive calls are needed to perform - * additional commands. - * - * Method locks the command queue. - */ - void cmdDoWork(); -#endif public: LLUUID mDebugID; @@ -172,6 +122,11 @@ private: LLMutex mQueueMutex; //to protect mRequestMap only LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. +public: + static LLStat sCacheHitRate; + static LLStat sCacheReadLatency; +private: + LLTextureCache* mTextureCache; LLImageDecodeThread* mImageDecodeThread; @@ -193,30 +148,6 @@ private: //debug use U32 mTotalHTTPRequests ; -#if HTTP_METRICS - // Out-of-band cross-thread command queue. This command queue - // is logically tied to LLQueuedThread's list of - // QueuedRequest instances and so must be covered by the - // same locks. - typedef std::vector command_queue_t; - command_queue_t mCommands; - - // If true, modifies some behaviors that help with QA tasks. - const bool mQAMode; - - // Count of POST requests outstanding. We maintain the count - // indirectly in the CURL request responder's ctor and dtor and - // use it when determining whether or not to sleep the thread. Can't - // use the LLCurl module's request counter as it isn't thread compatible. - // *NOTE: Don't mix Atomic and static, apr_initialize must be called first. - LLAtomic32 mCurlPOSTRequestCount; - -public: - // A probabilistically-correct indicator that the current - // attempt to log metrics follows a break in the metrics stream - // reporting due to either startup or a problem POSTing data. - static volatile bool svMetricsDataBreak; -#endif }; #endif // LL_LLTEXTUREFETCH_H diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp index c758d8909..ca71d11a8 100644 --- a/indra/newview/llviewermessage.cpp +++ b/indra/newview/llviewermessage.cpp @@ -5179,6 +5179,18 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data) case LL_SIM_STAT_IOPUMPTIME: LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value); break; + case LL_SIM_STAT_PCTSCRIPTSRUN: + LLViewerStats::getInstance()->mSimPctScriptsRun.addValue(stat_value); + break; + case LL_SIM_STAT_SIMAISTEPTIMEMS: + LLViewerStats::getInstance()->mSimSimAIStepMsec.addValue(stat_value); + break; + case LL_SIM_STAT_SKIPPEDAISILSTEPS_PS: + LLViewerStats::getInstance()->mSimSimSkippedSilhouetteSteps.addValue(stat_value); + break; + case LL_SIM_STAT_PCTSTEPPEDCHARACTERS: + LLViewerStats::getInstance()->mSimSimPctSteppedCharacters.addValue(stat_value); + break; default: // Used to be a commented out warning. LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL; diff --git a/indra/newview/llviewerobjectlist.cpp b/indra/newview/llviewerobjectlist.cpp index ae919f7f7..ddcb84554 100644 --- a/indra/newview/llviewerobjectlist.cpp +++ b/indra/newview/llviewerobjectlist.cpp @@ -66,6 +66,7 @@ #include "llsdutil.h" #include "llviewerregion.h" #include "llviewerstats.h" +#include "llviewerstatsrecorder.h" #include "llvovolume.h" #include "llvoavatarself.h" #include "lltoolmgr.h" @@ -113,6 +114,7 @@ extern LLPipeline gPipeline; U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. std::map LLViewerObjectList::sIPAndPortToIndex; std::map LLViewerObjectList::sIndexAndLocalIDToUUID; +LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128); LLViewerObjectList::LLViewerObjectList() { @@ -384,11 +386,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, U8 compressed_dpbuffer[2048]; LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); LLDataPacker *cached_dpp = NULL; + LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance(); for (i = 0; i < num_objects; i++) { + // timer is unused? LLTimer update_timer; BOOL justCreated = FALSE; + S32 msg_size = 0; if (cached) { @@ -396,6 +401,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, U32 crc; mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, i); + msg_size += sizeof(U32) * 2; // Lookup data packer and add this id to cache miss lists if necessary. U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; @@ -411,9 +417,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, else { // Cache Miss. - #if LL_RECORD_VIEWER_STATS - LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type); - #endif + recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size); continue; // no data packer, skip this object } @@ -433,8 +437,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); - - if (update_type != OUT_TERSE_IMPROVED) + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { compressed_dp.unpackUUID(fullid, "ID"); compressed_dp.unpackU32(local_id, "LocalID"); @@ -454,9 +457,11 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } } } - else if (update_type != OUT_FULL) + else if (update_type != OUT_FULL) // !compressed, !OUT_FULL ==> OUT_FULL_CACHED only? { mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + msg_size += sizeof(U32); + getUUIDFromLocal(fullid, local_id, gMessageSystem->getSenderIP(), @@ -467,10 +472,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, mNumUnknownUpdates++; } } - else + else // OUT_FULL only? { mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i); + msg_size += sizeof(LLUUID); + msg_size += sizeof(U32); // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl; } objectp = findObject(fullid); @@ -515,28 +522,33 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, { if (update_type == OUT_TERSE_IMPROVED) { - // llinfos << "terse update for an unknown object:" << fullid << llendl; + // llinfos << "terse update for an unknown object (compressed):" << fullid << llendl; + recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } } - else if (cached) + else if (cached) // Cache hit only? { } else { if (update_type != OUT_FULL) { - // llinfos << "terse update for an unknown object:" << fullid << llendl; + //llinfos << "terse update for an unknown object:" << fullid << llendl; + recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); + msg_size += sizeof(U8); + } #ifdef IGNORE_DEAD if (mDeadObjects.find(fullid) != mDeadObjects.end()) { mNumDeadObjectUpdates++; - // llinfos << "update for a dead object:" << fullid << llendl; + //llinfos << "update for a dead object:" << fullid << llendl; + recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } #endif @@ -553,10 +565,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); if (!objectp) { + llinfos << "createObject failure for object: " << fullid << llendl; + recorder.objectUpdateFailure(local_id, update_type, msg_size); continue; } justCreated = TRUE; mNumNewObjects++; + sCacheHitRate.addValue(cached ? 100.f : 0.f); + } @@ -568,15 +584,16 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, bool bCached = false; if (compressed) { - if (update_type != OUT_TERSE_IMPROVED) + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { objectp->mLocalID = local_id; } processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); - if (update_type != OUT_TERSE_IMPROVED) + if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only? { bCached = true; - objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); + LLViewerRegion::eCacheUpdateResult result = objectp->mRegionp->cacheFullUpdate(objectp, compressed_dp); + recorder.cacheFullUpdate(local_id, update_type, result, objectp, msg_size); } } else if (cached) @@ -592,11 +609,13 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys, } processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); } - + recorder.objectUpdateEvent(local_id, update_type, objectp, msg_size); objectp->setLastUpdateType(update_type); objectp->setLastUpdateCached(bCached); } + recorder.log(0.2f); + LLVOAvatar::cullAvatarsByPixelArea(); } diff --git a/indra/newview/llviewerobjectlist.h b/indra/newview/llviewerobjectlist.h index 5a48656b7..4f67c2691 100644 --- a/indra/newview/llviewerobjectlist.h +++ b/indra/newview/llviewerobjectlist.h @@ -205,6 +205,8 @@ public: std::vector mOrphanChildren; // UUID's of orphaned objects S32 mNumOrphans; + static LLStat sCacheHitRate; + typedef std::vector > vobj_list_t; vobj_list_t mObjects; diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index d300694cb..be87807f1 100644 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -1405,11 +1405,8 @@ void LLViewerRegion::requestCacheMisses() mCacheDirty = TRUE ; // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; - #if LL_RECORD_VIEWER_STATS - LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); - LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count); - LLViewerStatsRecorder::instance()->endObjectUpdateEvents(); - #endif + LLViewerStatsRecorder::instance().requestCacheMissesEvent(full_count + crc_count); + LLViewerStatsRecorder::instance().log(0.2f); } void LLViewerRegion::dumpCache() diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp index eeb96dfa6..16f494715 100644 --- a/indra/newview/llviewerstats.cpp +++ b/indra/newview/llviewerstats.cpp @@ -239,6 +239,9 @@ LLViewerStats::LLViewerStats() : mSimSimPhysicsStepMsec("simsimphysicsstepmsec"), mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"), mSimSimPhysicsOtherMsec("simsimphysicsothermsec"), + mSimSimAIStepMsec("simsimaistepmsec"), + mSimSimSkippedSilhouetteSteps("simsimskippedsilhouettesteps"), + mSimSimPctSteppedCharacters("simsimpctsteppedcharacters"), mSimAgentMsec("simagentmsec"), mSimImagesMsec("simimagesmsec"), mSimScriptMsec("simscriptmsec"), @@ -250,6 +253,7 @@ LLViewerStats::LLViewerStats() : mSimObjects("simobjects"), mSimActiveObjects("simactiveobjects"), mSimActiveScripts("simactivescripts"), + mSimPctScriptsRun("simpctscriptsrun"), mSimInPPS("siminpps"), mSimOutPPS("simoutpps"), mSimPendingDownloads("simpendingdownloads"), @@ -292,19 +296,19 @@ LLViewerStats::~LLViewerStats() void LLViewerStats::resetStats() { - LLViewerStats::getInstance()->mKBitStat.reset(); - LLViewerStats::getInstance()->mLayersKBitStat.reset(); - LLViewerStats::getInstance()->mObjectKBitStat.reset(); - LLViewerStats::getInstance()->mTextureKBitStat.reset(); - LLViewerStats::getInstance()->mVFSPendingOperations.reset(); - LLViewerStats::getInstance()->mAssetKBitStat.reset(); - LLViewerStats::getInstance()->mPacketsInStat.reset(); - LLViewerStats::getInstance()->mPacketsLostStat.reset(); - LLViewerStats::getInstance()->mPacketsOutStat.reset(); - LLViewerStats::getInstance()->mFPSStat.reset(); - LLViewerStats::getInstance()->mTexturePacketsStat.reset(); - - LLViewerStats::getInstance()->mAgentPositionSnaps.reset(); + LLViewerStats& stats = LLViewerStats::instance(); + stats.mKBitStat.reset(); + stats.mLayersKBitStat.reset(); + stats.mObjectKBitStat.reset(); + stats.mTextureKBitStat.reset(); + stats.mVFSPendingOperations.reset(); + stats.mAssetKBitStat.reset(); + stats.mPacketsInStat.reset(); + stats.mPacketsLostStat.reset(); + stats.mPacketsOutStat.reset(); + stats.mFPSStat.reset(); + stats.mTexturePacketsStat.reset(); + stats.mAgentPositionSnaps.reset(); } @@ -329,55 +333,55 @@ void LLViewerStats::updateFrameStats(const F64 time_diff) { if (mPacketsLostPercentStat.getCurrent() > 5.0) { - incStat(LLViewerStats::ST_LOSS_05_SECONDS, time_diff); + incStat(ST_LOSS_05_SECONDS, time_diff); } if (mSimFPS.getCurrent() < 20.f && mSimFPS.getCurrent() > 0.f) { - incStat(LLViewerStats::ST_SIM_FPS_20_SECONDS, time_diff); + incStat(ST_SIM_FPS_20_SECONDS, time_diff); } if (mSimPhysicsFPS.getCurrent() < 20.f && mSimPhysicsFPS.getCurrent() > 0.f) { - incStat(LLViewerStats::ST_PHYS_FPS_20_SECONDS, time_diff); + incStat(ST_PHYS_FPS_20_SECONDS, time_diff); } if (time_diff >= 0.5) { - incStat(LLViewerStats::ST_FPS_2_SECONDS, time_diff); + incStat(ST_FPS_2_SECONDS, time_diff); } if (time_diff >= 0.125) { - incStat(LLViewerStats::ST_FPS_8_SECONDS, time_diff); + incStat(ST_FPS_8_SECONDS, time_diff); } if (time_diff >= 0.1) { - incStat(LLViewerStats::ST_FPS_10_SECONDS, time_diff); + incStat(ST_FPS_10_SECONDS, time_diff); } if (gFrameCount && mLastTimeDiff > 0.0) { // new "stutter" meter - setStat(LLViewerStats::ST_FPS_DROP_50_RATIO, - (getStat(LLViewerStats::ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + + setStat(ST_FPS_DROP_50_RATIO, + (getStat(ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount); // old stats that were never really used - setStat(LLViewerStats::ST_FRAMETIME_JITTER, - (getStat(LLViewerStats::ST_FRAMETIME_JITTER) * (gFrameCount - 1) + + setStat(ST_FRAMETIME_JITTER, + (getStat(ST_FRAMETIME_JITTER) * (gFrameCount - 1) + fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount); F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount; - setStat(LLViewerStats::ST_FRAMETIME_SLEW, - (getStat(LLViewerStats::ST_FRAMETIME_SLEW) * (gFrameCount - 1) + + setStat(ST_FRAMETIME_SLEW, + (getStat(ST_FRAMETIME_SLEW) * (gFrameCount - 1) + fabs(average_frametime - time_diff) / average_frametime) / gFrameCount); F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth; - setStat(LLViewerStats::ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f); + setStat(ST_DELTA_BANDWIDTH, delta_bandwidth / 1024.f); - setStat(LLViewerStats::ST_MAX_BANDWIDTH, max_bandwidth / 1024.f); + setStat(ST_MAX_BANDWIDTH, max_bandwidth / 1024.f); } @@ -571,25 +575,20 @@ F32 gWorstLandCompression = 0.f, gWorstWaterCompression = 0.f; U32 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0; U32 gObjectBits = 0; F32 gAvgSimPing = 0.f; -U32 gTotalTextureBytesPerBoostLevel[LLViewerTexture::MAX_GL_IMAGE_CATEGORY] = {0}; +U32 gTotalTextureBytesPerBoostLevel[LLGLTexture::MAX_GL_IMAGE_CATEGORY] = {0}; extern U32 gVisCompared; extern U32 gVisTested; -std::map gDebugTimers; -std::map gDebugTimerLabel; +LLFrameTimer gTextureTimer; -void init_statistics() -{ - // Label debug timers - gDebugTimerLabel[0] = "Texture"; -} - -void update_statistics(U32 frame_count) +void update_statistics() { gTotalWorldBytes += gVLManager.getTotalBytes(); gTotalObjectBytes += gObjectBits / 8; + LLViewerStats& stats = LLViewerStats::instance(); + // make sure we have a valid time delta for this frame if (gFrameIntervalSeconds > 0.f) { @@ -606,51 +605,51 @@ void update_statistics(U32 frame_count) LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds); } } - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); + stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); + stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); + stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); + stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); #if 0 // 1.9.2 LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment")); #endif - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame")); + stats.setStat(LLViewerStats::ST_FRAME_SECS, gDebugView->mFastTimerView->getTime("Frame")); F64 idle_secs = gDebugView->mFastTimerView->getTime("Idle"); F64 network_secs = gDebugView->mFastTimerView->getTime("Network"); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry")); + stats.setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); + stats.setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); + stats.setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); + stats.setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); + stats.setStat(LLViewerStats::ST_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry")); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); if (cdp) { - LLViewerStats::getInstance()->mSimPingStat.addValue(cdp->getPingDelay()); + stats.mSimPingStat.addValue(cdp->getPingDelay()); gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); gSimPingCount++; } else { - LLViewerStats::getInstance()->mSimPingStat.addValue(10000); + stats.mSimPingStat.addValue(10000); } - LLViewerStats::getInstance()->mFPSStat.addValue(1); + stats.mFPSStat.addValue(1); F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits()); - LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f); - LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f); - LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); - LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); + stats.mLayersKBitStat.addValue(layer_bits/1024.f); + stats.mObjectKBitStat.addValue(gObjectBits/1024.f); + stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); + stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); gTransferManager.resetTransferBitsIn(LLTCT_ASSET); if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) { - gDebugTimers[0].pause(); + gTextureTimer.pause(); } else { - gDebugTimers[0].unpause(); + gTextureTimer.unpause(); } { @@ -662,7 +661,7 @@ void update_statistics(U32 frame_count) visible_avatar_frames = 1.f; avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames; } - LLViewerStats::getInstance()->setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars); + stats.setStat(LLViewerStats::ST_VISIBLE_AVATARS, (F64)avg_visible_avatars); } LLWorld::getInstance()->updateNetStats(); LLWorld::getInstance()->requestCacheMisses(); @@ -672,14 +671,14 @@ void update_statistics(U32 frame_count) gObjectBits = 0; // gDecodedBits = 0; - //Update bandwidth stats often because texture fetch relies on them. + // Only update texture stats periodically so that they are less noisy { - static const F32 texture_stats_freq = 0.1f; + static const F32 texture_stats_freq = 10.f; static LLFrameTimer texture_stats_timer; if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) { - LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); - LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); + stats.mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); + stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerTextureList::sTextureBits/1024.f/texture_stats_timer.getElapsedTimeF32()); gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; LLViewerTextureList::sTextureBits = 0; @@ -693,7 +692,7 @@ void update_statistics(U32 frame_count) static LLFrameTimer mem_stats_timer; if (mem_stats_timer.getElapsedTimeF32() >= mem_stats_freq) { - LLViewerStats::getInstance()->mMallocStat.addValue(SGMemStat::getMalloc()/1024.f/1024.f); + stats.mMallocStat.addValue(SGMemStat::getMalloc()/1024.f/1024.f); mem_stats_timer.reset(); } } @@ -813,6 +812,7 @@ void send_stats() system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass(); system["gpu_vendor"] = gGLManager.mGLVendorShort; system["gpu_version"] = gGLManager.mDriverVersionVendorString; + system["opengl_version"] = gGLManager.mGLVersionString; LLSD &download = body["downloads"]; @@ -859,10 +859,7 @@ void send_stats() S32 window_height = gViewerWindow->getWindowHeightRaw(); S32 window_size = (window_width * window_height) / 1024; misc["string_1"] = llformat("%d", window_size); - if (gDebugTimers.find(0) != gDebugTimers.end() && gFrameTimeSeconds > 0) - { - misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f", gDebugTimers[0].getElapsedTimeF32(), gFrameTimeSeconds); - } + misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f", gTextureTimer.getElapsedTimeF32(), gFrameTimeSeconds); // misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21 // misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21 diff --git a/indra/newview/llviewerstats.h b/indra/newview/llviewerstats.h index 93d482da7..264b02bf2 100644 --- a/indra/newview/llviewerstats.h +++ b/indra/newview/llviewerstats.h @@ -39,88 +39,91 @@ class LLViewerStats : public LLSingleton { public: - LLStat mKBitStat; - LLStat mLayersKBitStat; - LLStat mObjectKBitStat; - LLStat mAssetKBitStat; - LLStat mTextureKBitStat; - LLStat mVFSPendingOperations; - LLStat mObjectsDrawnStat; - LLStat mObjectsCulledStat; - LLStat mObjectsTestedStat; - LLStat mObjectsComparedStat; - LLStat mObjectsOccludedStat; - LLStat mFPSStat; - LLStat mPacketsInStat; - LLStat mPacketsLostStat; - LLStat mPacketsOutStat; - LLStat mPacketsLostPercentStat; - LLStat mTexturePacketsStat; - LLStat mActualInKBitStat; // From the packet ring (when faking a bad connection) - LLStat mActualOutKBitStat; // From the packet ring (when faking a bad connection) - LLStat mTrianglesDrawnStat; - LLStat mMallocStat; + LLStat mKBitStat, + mLayersKBitStat, + mObjectKBitStat, + mAssetKBitStat, + mTextureKBitStat, + mVFSPendingOperations, + mObjectsDrawnStat, + mObjectsCulledStat, + mObjectsTestedStat, + mObjectsComparedStat, + mObjectsOccludedStat, + mFPSStat, + mPacketsInStat, + mPacketsLostStat, + mPacketsOutStat, + mPacketsLostPercentStat, + mTexturePacketsStat, + mActualInKBitStat, // From the packet ring (when faking a bad connection) + mActualOutKBitStat, // From the packet ring (when faking a bad connection) + mTrianglesDrawnStat, + mMallocStat; // Simulator stats - LLStat mSimTimeDilation; + LLStat mSimTimeDilation, - LLStat mSimFPS; - LLStat mSimPhysicsFPS; - LLStat mSimAgentUPS; - LLStat mSimScriptEPS; + mSimFPS, + mSimPhysicsFPS, + mSimAgentUPS, + mSimScriptEPS, - LLStat mSimFrameMsec; - LLStat mSimNetMsec; - LLStat mSimSimOtherMsec; - LLStat mSimSimPhysicsMsec; + mSimFrameMsec, + mSimNetMsec, + mSimSimOtherMsec, + mSimSimPhysicsMsec, - LLStat mSimSimPhysicsStepMsec; - LLStat mSimSimPhysicsShapeUpdateMsec; - LLStat mSimSimPhysicsOtherMsec; + mSimSimPhysicsStepMsec, + mSimSimPhysicsShapeUpdateMsec, + mSimSimPhysicsOtherMsec, + mSimSimAIStepMsec, + mSimSimSkippedSilhouetteSteps, + mSimSimPctSteppedCharacters, - LLStat mSimAgentMsec; - LLStat mSimImagesMsec; - LLStat mSimScriptMsec; - LLStat mSimSpareMsec; - LLStat mSimSleepMsec; - LLStat mSimPumpIOMsec; + mSimAgentMsec, + mSimImagesMsec, + mSimScriptMsec, + mSimSpareMsec, + mSimSleepMsec, + mSimPumpIOMsec, - LLStat mSimMainAgents; - LLStat mSimChildAgents; - LLStat mSimObjects; - LLStat mSimActiveObjects; - LLStat mSimActiveScripts; + mSimMainAgents, + mSimChildAgents, + mSimObjects, + mSimActiveObjects, + mSimActiveScripts, + mSimPctScriptsRun, - LLStat mSimInPPS; - LLStat mSimOutPPS; - LLStat mSimPendingDownloads; - LLStat mSimPendingUploads; - LLStat mSimPendingLocalUploads; - LLStat mSimTotalUnackedBytes; + mSimInPPS, + mSimOutPPS, + mSimPendingDownloads, + mSimPendingUploads, + mSimPendingLocalUploads, + mSimTotalUnackedBytes, - LLStat mPhysicsPinnedTasks; - LLStat mPhysicsLODTasks; - LLStat mPhysicsMemoryAllocated; + mPhysicsPinnedTasks, + mPhysicsLODTasks, + mPhysicsMemoryAllocated, - LLStat mSimPingStat; + mSimPingStat, - LLStat mNumImagesStat; - LLStat mNumRawImagesStat; - LLStat mGLTexMemStat; - LLStat mGLBoundMemStat; - LLStat mRawMemStat; - LLStat mFormattedMemStat; + mNumImagesStat, + mNumRawImagesStat, + mGLTexMemStat, + mGLBoundMemStat, + mRawMemStat, + mFormattedMemStat, - LLStat mNumObjectsStat; - LLStat mNumActiveObjectsStat; - LLStat mNumNewObjectsStat; - LLStat mNumSizeCulledStat; - LLStat mNumVisCulledStat; + mNumObjectsStat, + mNumActiveObjectsStat, + mNumNewObjectsStat, + mNumSizeCulledStat, + mNumVisCulledStat; void resetStats(); public: - // If you change this, please also add a corresponding text label - // in statTypeToText in llviewerstats.cpp + // If you change this, please also add a corresponding text label in llviewerstats.cpp enum EStatType { ST_VERSION = 0, @@ -251,7 +254,7 @@ public: inline F32 getStdDev() const { const F32 mean = getMean(); - return (mCount == 0) ? 0.f : sqrt( mSumOfSquares/mCount - (mean * mean) ); + return (mCount < 2) ? 0.f : sqrt(llmax(0.f,mSumOfSquares/mCount - (mean * mean))); } inline U32 getCount() const @@ -291,14 +294,12 @@ private: static const F32 SEND_STATS_PERIOD = 300.0f; // The following are from (older?) statistics code found in appviewer. -void init_statistics(); void reset_statistics(); void output_statistics(void*); -void update_statistics(U32 frame_count); +void update_statistics(); void send_stats(); -extern std::map gDebugTimers; -extern std::map gDebugTimerLabel; +extern LLFrameTimer gTextureTimer; extern U32 gTotalTextureBytes; extern U32 gTotalObjectBytes; extern U32 gTotalTextureBytesPerBoostLevel[] ; diff --git a/indra/newview/llviewerstatsrecorder.cpp b/indra/newview/llviewerstatsrecorder.cpp index e9d21b484..91e485d01 100644 --- a/indra/newview/llviewerstatsrecorder.cpp +++ b/indra/newview/llviewerstatsrecorder.cpp @@ -27,7 +27,6 @@ #include "llviewerprecompiledheaders.h" #include "llviewerstatsrecorder.h" -#if LL_RECORD_VIEWER_STATS #include "llfile.h" #include "llviewerregion.h" @@ -45,9 +44,8 @@ LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL; LLViewerStatsRecorder::LLViewerStatsRecorder() : mObjectCacheFile(NULL), mTimer(), - mRegionp(NULL), - mStartTime(0.f), - mProcessingTime(0.f) + mStartTime(0.0), + mLastSnapshotTime(0.0) { if (NULL != sInstance) { @@ -61,112 +59,77 @@ LLViewerStatsRecorder::~LLViewerStatsRecorder() { if (mObjectCacheFile != NULL) { + // last chance snapshot + writeToLog(0.f); LLFile::close(mObjectCacheFile); mObjectCacheFile = NULL; } } -// static -void LLViewerStatsRecorder::initClass() -{ - sInstance = new LLViewerStatsRecorder(); -} - -// static -void LLViewerStatsRecorder::cleanupClass() -{ - delete sInstance; - sInstance = NULL; -} - - -void LLViewerStatsRecorder::initStatsRecorder(LLViewerRegion *regionp) -{ - if (mObjectCacheFile == NULL) - { - mStartTime = LLTimer::getTotalTime(); - mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb"); - if (mObjectCacheFile) - { // Write column headers - std::ostringstream data_msg; - data_msg << "EventTime, " - << "ProcessingTime, " - << "CacheHits, " - << "CacheFullMisses, " - << "CacheCrcMisses, " - << "FullUpdates, " - << "TerseUpdates, " - << "CacheMissRequests, " - << "CacheMissResponses, " - << "CacheUpdateDupes, " - << "CacheUpdateChanges, " - << "CacheUpdateAdds, " - << "CacheUpdateReplacements, " - << "UpdateFailures" - << "\n"; - - fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); - } - } -} - -void LLViewerStatsRecorder::beginObjectUpdateEvents(LLViewerRegion *regionp) -{ - initStatsRecorder(regionp); - mRegionp = regionp; - mProcessingTime = LLTimer::getTotalTime(); - clearStats(); -} - void LLViewerStatsRecorder::clearStats() { mObjectCacheHitCount = 0; + mObjectCacheHitSize = 0; mObjectCacheMissFullCount = 0; + mObjectCacheMissFullSize = 0; mObjectCacheMissCrcCount = 0; + mObjectCacheMissCrcSize = 0; mObjectFullUpdates = 0; + mObjectFullUpdatesSize = 0; mObjectTerseUpdates = 0; + mObjectTerseUpdatesSize = 0; mObjectCacheMissRequests = 0; mObjectCacheMissResponses = 0; + mObjectCacheMissResponsesSize = 0; mObjectCacheUpdateDupes = 0; mObjectCacheUpdateChanges = 0; mObjectCacheUpdateAdds = 0; mObjectCacheUpdateReplacements = 0; mObjectUpdateFailures = 0; + mObjectUpdateFailuresSize = 0; + mTextureFetchSize = 0; } -void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type) +void LLViewerStatsRecorder::recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size) { mObjectUpdateFailures++; + mObjectUpdateFailuresSize += msg_size; } -void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type) +void LLViewerStatsRecorder::recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size) { if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type) { mObjectCacheMissFullCount++; + mObjectCacheMissFullSize += msg_size; } else { mObjectCacheMissCrcCount++; + mObjectCacheMissCrcSize += msg_size; } } -void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp) +void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size) { switch (update_type) { case OUT_FULL: mObjectFullUpdates++; + mObjectFullUpdatesSize += msg_size; break; case OUT_TERSE_IMPROVED: mObjectTerseUpdates++; + mObjectTerseUpdatesSize += msg_size; break; case OUT_FULL_COMPRESSED: mObjectCacheMissResponses++; + mObjectCacheMissResponsesSize += msg_size; break; case OUT_FULL_CACHED: mObjectCacheHitCount++; + mObjectCacheHitSize += msg_size; break; default: llwarns << "Unknown update_type" << llendl; @@ -174,7 +137,7 @@ void LLViewerStatsRecorder::recordObjectUpdateEvent(U32 local_id, const EObjectU }; } -void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp) +void LLViewerStatsRecorder::recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size) { switch (update_result) { @@ -201,9 +164,15 @@ void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count) mObjectCacheMissRequests += count; } -void LLViewerStatsRecorder::endObjectUpdateEvents() +void LLViewerStatsRecorder::writeToLog( F32 interval ) { - llinfos << "ILX: " + F64 delta_time = LLTimer::getTotalSeconds() - mLastSnapshotTime; + S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; + + if ( delta_time < interval || total_objects == 0) return; + + mLastSnapshotTime = LLTimer::getTotalSeconds(); + lldebugs << "ILX: " << mObjectCacheHitCount << " hits, " << mObjectCacheMissFullCount << " full misses, " << mObjectCacheMissCrcCount << " crc misses, " @@ -218,41 +187,81 @@ void LLViewerStatsRecorder::endObjectUpdateEvents() << mObjectUpdateFailures << " update failures" << llendl; - S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; - if (mObjectCacheFile != NULL && - total_objects > 0) + if (mObjectCacheFile == NULL) { - std::ostringstream data_msg; - F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0); + mStartTime = LLTimer::getTotalSeconds(); + mObjectCacheFile = LLFile::fopen(STATS_FILE_NAME, "wb"); + if (mObjectCacheFile) + { // Write column headers + std::ostringstream data_msg; + data_msg << "EventTime(ms)\t" + << "Cache Hits\t" + << "Cache Full Misses\t" + << "Cache Crc Misses\t" + << "Full Updates\t" + << "Terse Updates\t" + << "Cache Miss Requests\t" + << "Cache Miss Responses\t" + << "Cache Update Dupes\t" + << "Cache Update Changes\t" + << "Cache Update Adds\t" + << "Cache Update Replacements\t" + << "Update Failures\t" + << "Cache Hits bps\t" + << "Cache Full Misses bps\t" + << "Cache Crc Misses bps\t" + << "Full Updates bps\t" + << "Terse Updates bps\t" + << "Cache Miss Responses bps\t" + << "Texture Fetch bps\t" + << "\n"; - data_msg << getTimeSinceStart() - << ", " << processing32 - << ", " << mObjectCacheHitCount - << ", " << mObjectCacheMissFullCount - << ", " << mObjectCacheMissCrcCount - << ", " << mObjectFullUpdates - << ", " << mObjectTerseUpdates - << ", " << mObjectCacheMissRequests - << ", " << mObjectCacheMissResponses - << ", " << mObjectCacheUpdateDupes - << ", " << mObjectCacheUpdateChanges - << ", " << mObjectCacheUpdateAdds - << ", " << mObjectCacheUpdateReplacements - << ", " << mObjectUpdateFailures - << "\n"; - - fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); + fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); + } + else + { + llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl; + return; + } } + std::ostringstream data_msg; + + data_msg << getTimeSinceStart() + << "\t " << mObjectCacheHitCount + << "\t" << mObjectCacheMissFullCount + << "\t" << mObjectCacheMissCrcCount + << "\t" << mObjectFullUpdates + << "\t" << mObjectTerseUpdates + << "\t" << mObjectCacheMissRequests + << "\t" << mObjectCacheMissResponses + << "\t" << mObjectCacheUpdateDupes + << "\t" << mObjectCacheUpdateChanges + << "\t" << mObjectCacheUpdateAdds + << "\t" << mObjectCacheUpdateReplacements + << "\t" << mObjectUpdateFailures + << "\t" << (mObjectCacheHitSize * 8 / delta_time) + << "\t" << (mObjectCacheMissFullSize * 8 / delta_time) + << "\t" << (mObjectCacheMissCrcSize * 8 / delta_time) + << "\t" << (mObjectFullUpdatesSize * 8 / delta_time) + << "\t" << (mObjectTerseUpdatesSize * 8 / delta_time) + << "\t" << (mObjectCacheMissResponsesSize * 8 / delta_time) + << "\t" << (mTextureFetchSize * 8 / delta_time) + << "\n"; + + fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile ); clearStats(); } F32 LLViewerStatsRecorder::getTimeSinceStart() { - return (F32) ((LLTimer::getTotalTime() - mStartTime) / 1000.0); + return (F32) (LLTimer::getTotalSeconds() - mStartTime); } -#endif +void LLViewerStatsRecorder::recordTextureFetch( S32 msg_size ) +{ + mTextureFetchSize += msg_size; +} diff --git a/indra/newview/llviewerstatsrecorder.h b/indra/newview/llviewerstatsrecorder.h index 612ac380f..d1744f491 100644 --- a/indra/newview/llviewerstatsrecorder.h +++ b/indra/newview/llviewerstatsrecorder.h @@ -35,63 +35,111 @@ #define LL_RECORD_VIEWER_STATS 0 -#if LL_RECORD_VIEWER_STATS #include "llframetimer.h" #include "llviewerobject.h" #include "llviewerregion.h" class LLMutex; -class LLViewerRegion; class LLViewerObject; -class LLViewerStatsRecorder +class LLViewerStatsRecorder : public LLSingleton { public: + LOG_CLASS(LLViewerStatsRecorder); LLViewerStatsRecorder(); ~LLViewerStatsRecorder(); - static void initClass(); - static void cleanupClass(); - static LLViewerStatsRecorder* instance() {return sInstance; } + void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size) + { +#if LL_RECORD_VIEWER_STATS + recordObjectUpdateFailure(local_id, update_type, msg_size); +#endif + } - void initStatsRecorder(LLViewerRegion *regionp); + void cacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size) + { +#if LL_RECORD_VIEWER_STATS + recordCacheMissEvent(local_id, update_type, cache_miss_type, msg_size); +#endif + } - void beginObjectUpdateEvents(LLViewerRegion *regionp); - void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type); - void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type); - void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp); - void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp); - void recordRequestCacheMissesEvent(S32 count); - void endObjectUpdateEvents(); + void objectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size) + { +#if LL_RECORD_VIEWER_STATS + recordObjectUpdateEvent(local_id, update_type, objectp, msg_size); +#endif + } + + void cacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size) + { +#if LL_RECORD_VIEWER_STATS + recordCacheFullUpdate(local_id, update_type, update_result, objectp, msg_size); +#endif + } + + void requestCacheMissesEvent(S32 count) + { +#if LL_RECORD_VIEWER_STATS + recordRequestCacheMissesEvent(count); +#endif + } + + void textureFetch(S32 msg_size) + { +#if LL_RECORD_VIEWER_STATS + recordTextureFetch(msg_size); +#endif + } + + void log(F32 interval) + { +#if LL_RECORD_VIEWER_STATS + writeToLog(interval); +#endif + } F32 getTimeSinceStart(); private: + void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size); + void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type, S32 msg_size); + void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size); + void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp, S32 msg_size); + void recordRequestCacheMissesEvent(S32 count); + void recordTextureFetch(S32 msg_size); + void writeToLog(F32 interval); + static LLViewerStatsRecorder* sInstance; LLFILE * mObjectCacheFile; // File to write data into LLFrameTimer mTimer; - LLViewerRegion* mRegionp; F64 mStartTime; - F64 mProcessingTime; + F64 mLastSnapshotTime; S32 mObjectCacheHitCount; + S32 mObjectCacheHitSize; S32 mObjectCacheMissFullCount; + S32 mObjectCacheMissFullSize; S32 mObjectCacheMissCrcCount; + S32 mObjectCacheMissCrcSize; S32 mObjectFullUpdates; + S32 mObjectFullUpdatesSize; S32 mObjectTerseUpdates; + S32 mObjectTerseUpdatesSize; S32 mObjectCacheMissRequests; S32 mObjectCacheMissResponses; + S32 mObjectCacheMissResponsesSize; S32 mObjectCacheUpdateDupes; S32 mObjectCacheUpdateChanges; S32 mObjectCacheUpdateAdds; S32 mObjectCacheUpdateReplacements; S32 mObjectUpdateFailures; + S32 mObjectUpdateFailuresSize; + S32 mTextureFetchSize; void clearStats(); }; -#endif // LL_RECORD_VIEWER_STATS #endif // LLVIEWERSTATSRECORDER_H diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp index 981421b99..d57a05a46 100644 --- a/indra/newview/llviewertexturelist.cpp +++ b/indra/newview/llviewertexturelist.cpp @@ -980,14 +980,6 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time) break; } } - //if (fetch_count == 0) - //{ - // gDebugTimers[0].pause(); - //} - //else - //{ - // gDebugTimers[0].unpause(); - //} return image_op_timer.getElapsedTimeF32(); } diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp index c5f44f342..b44870e21 100644 --- a/indra/newview/llviewerwindow.cpp +++ b/indra/newview/llviewerwindow.cpp @@ -318,27 +318,24 @@ public: static const LLCachedControl debug_show_time("DebugShowTime"); if (debug_show_time) { - const U32 y_inc2 = 15; - for (std::map::reverse_iterator iter = gDebugTimers.rbegin(); - iter != gDebugTimers.rend(); ++iter) { - S32 idx = iter->first; - LLFrameTimer& timer = iter->second; + const U32 y_inc2 = 15; + LLFrameTimer& timer = gTextureTimer; F32 time = timer.getElapsedTimeF32(); S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); - std::string label = gDebugTimerLabel[idx]; - if (label.empty()) label = llformat("Debug: %d", idx); - addText(xpos, ypos, llformat(" %s: %d:%02d:%02d", label.c_str(), hours,mins,secs)); ypos += y_inc2; + addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2; } + { F32 time = gFrameTimeSeconds; S32 hours = (S32)(time / (60*60)); S32 mins = (S32)((time - hours*(60*60)) / 60); S32 secs = (S32)((time - hours*(60*60) - mins*60)); addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; } + } #if LL_WINDOWS static const LLCachedControl debug_show_memory("DebugShowMemory"); From 4cc35d6c664f50fdc835102c8c72e151f11535e3 Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 17 Feb 2013 02:54:30 -0600 Subject: [PATCH 17/18] Fixed up some silly issues with the client tag system. --- indra/llcommon/llsdutil.cpp | 2 +- .../newview/app_settings/settings_ascent.xml | 2 +- indra/newview/ascentprefsvan.cpp | 4 +- indra/newview/ascentprefsvan.h | 2 +- indra/newview/llvoavatar.cpp | 46 +++++++++++++------ indra/newview/llvoavatarself.cpp | 2 +- .../en-us/panel_preferences_ascent_vanity.xml | 4 +- 7 files changed, 41 insertions(+), 21 deletions(-) diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index 2c91b68ef..120bfa2c9 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -598,7 +598,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits) case LLSD::TypeReal: // This is where the 'bits' argument comes in handy. If passed // explicitly, it means to use is_approx_equal_fraction() to compare. - if (bits >= 0) + if (bits != -1) { return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits); } diff --git a/indra/newview/app_settings/settings_ascent.xml b/indra/newview/app_settings/settings_ascent.xml index 5a77d0f50..dd8d4e606 100644 --- a/indra/newview/app_settings/settings_ascent.xml +++ b/indra/newview/app_settings/settings_ascent.xml @@ -268,7 +268,7 @@ Value 1 - AscentUseTag + AscentBroadcastTag Comment Broadcast client tag diff --git a/indra/newview/ascentprefsvan.cpp b/indra/newview/ascentprefsvan.cpp index 2d9b32144..449745d5a 100644 --- a/indra/newview/ascentprefsvan.cpp +++ b/indra/newview/ascentprefsvan.cpp @@ -193,7 +193,7 @@ void LLPrefsAscentVan::refreshValues() mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata"); //Tags\Colors ---------------------------------------------------------------------------- - mAscentUseTag = gSavedSettings.getBOOL("AscentUseTag"); + mAscentBroadcastTag = gSavedSettings.getBOOL("AscentBroadcastTag"); mReportClientUUID = gSavedSettings.getString("AscentReportClientUUID"); mSelectedClient = gSavedSettings.getU32("AscentReportClientIndex"); mShowSelfClientTag = gSavedSettings.getBOOL("AscentShowSelfTag"); @@ -276,7 +276,7 @@ void LLPrefsAscentVan::cancel() gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata); //Tags\Colors ---------------------------------------------------------------------------- - gSavedSettings.setBOOL("AscentUseTag", mAscentUseTag); + gSavedSettings.setBOOL("AscentBroadcastTag", mAscentBroadcastTag); gSavedSettings.setString("AscentReportClientUUID", mReportClientUUID); gSavedSettings.setU32("AscentReportClientIndex", mSelectedClient); gSavedSettings.setBOOL("AscentShowSelfTag", mShowSelfClientTag); diff --git a/indra/newview/ascentprefsvan.h b/indra/newview/ascentprefsvan.h index 62600a264..4439205cc 100644 --- a/indra/newview/ascentprefsvan.h +++ b/indra/newview/ascentprefsvan.h @@ -63,7 +63,7 @@ protected: bool mAnnounceSnapshots; bool mAnnounceStreamMetadata; //Tags\Colors - BOOL mAscentUseTag; + BOOL mAscentBroadcastTag; std::string mReportClientUUID; U32 mSelectedClient; BOOL mShowSelfClientTag; diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 8108d2bd3..fee8c5253 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -567,10 +567,15 @@ SHClientTagMgr::SHClientTagMgr() gSavedSettings.getControl("AscentFriendColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); gSavedSettings.getControl("AscentMutedColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + //Following group of settings all actually manipulate the tag cache for agent avatar. Even if the tag system is 'disabled', we still allow an + //entry to exist for the agent avatar. gSavedSettings.getControl("AscentUseCustomTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); gSavedSettings.getControl("AscentCustomTagColor")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); gSavedSettings.getControl("AscentCustomTagLabel")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + //And because there can be an entry for the self avatar, always perform this as well. + gSavedSettings.getControl("AscentShowSelfTag")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + if(!getIsEnabled()) return; @@ -578,12 +583,14 @@ SHClientTagMgr::SHClientTagMgr() fetchDefinitions(); parseDefinitions(); - //These only matter to the agent avatar. Don't iterate over everything. - gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); + //Tags for other users only exist if the tag system is enabled. No point in registering this callback if non-agent avatars can't have tags. + gSavedSettings.getControl("AscentShowOthersTag")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); + + //Update the cached tag for the agent avatar. AscentReportClientUUID dictates what tag the agent avatar sees on their self. gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); - //Fire off a AgentSetAppearance update if these change. - gSavedSettings.getControl("AscentUseTag")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); + //Fire off a AgentSetAppearance update if these change. Essentially, forces the new clientid (or lack thereof) to be sent off to the server for others to see. + gSavedSettings.getControl("AscentBroadcastTag")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); } @@ -682,7 +689,6 @@ const LLSD SHClientTagMgr::generateClientTag(const LLVOAvatar* pAvatar) const if (pAvatar->isSelf()) { - static const LLCachedControl ascent_use_tag("AscentUseTag",true); static const LLCachedControl ascent_use_custom_tag("AscentUseCustomTag", false); static const LLCachedControl ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f)); static const LLCachedControl ascent_custom_tag_label("AscentCustomTagLabel","custom"); @@ -699,7 +705,7 @@ const LLSD SHClientTagMgr::generateClientTag(const LLVOAvatar* pAvatar) const { return LLSD(); } - else if (ascent_use_tag) + else { id.set(ascent_report_client_uuid,false); } @@ -796,24 +802,32 @@ void SHClientTagMgr::updateAvatarTag(LLVOAvatar* pAvatar) if(new_tag.isUndefined()) mAvatarTags.erase(id); else - mAvatarTags.insert(std::pair(id, new_tag)); + mAvatarTags[id]=new_tag; pAvatar->clearNameTag(); //LLVOAvatar::idleUpdateNameTag will pick up on mNameString being cleared. } } const std::string SHClientTagMgr::getClientName(const LLVOAvatar* pAvatar, bool is_friend) const { static LLCachedControl ascent_show_friends_tag("AscentShowFriendsTag", false); + static LLCachedControl ascent_show_self_tag("AscentShowSelfTag", false); + static LLCachedControl ascent_show_others_tag("AscentShowOthersTag", false); if(is_friend && ascent_show_friends_tag) return "Friend"; else { - LLSD tag; - std::map::const_iterator it = mAvatarTags.find(pAvatar->getID()); - if(it != mAvatarTags.end()) + if((!pAvatar->isSelf() && ascent_show_others_tag) || + (pAvatar->isSelf() && ascent_show_self_tag)) { - tag = it->second.get("name"); + LLSD tag; + std::map::const_iterator it = mAvatarTags.find(pAvatar->getID()); + if(it != mAvatarTags.end()) + { + tag = it->second.get("name"); + } + return tag.asString(); } - return tag.asString(); + else + return std::string(); } } const LLUUID SHClientTagMgr::getClientID(const LLVOAvatar* pAvatar) const @@ -3222,7 +3236,13 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) while ((index = line.find("%f")) != std::string::npos) line.replace(index, 2, firstnameText); while ((index = line.find("%l")) != std::string::npos) - line.replace(index, 2, lastnameText); + { + llinfos << "'" << line.substr(index) << "'" << llendl; + if(lastnameText.empty() && line[index+2] == ' ') //Entire displayname string crammed into firstname + line.replace(index, 3, ""); //so eat the extra space. + else + line.replace(index, 2, lastnameText); + } while ((index = line.find("%g")) != std::string::npos) line.replace(index, 2, groupText); while ((index = line.find("%t")) != std::string::npos) diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp index 78daf033c..566f773b1 100644 --- a/indra/newview/llvoavatarself.cpp +++ b/indra/newview/llvoavatarself.cpp @@ -2589,7 +2589,7 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const { LLTextureEntry* entry = getTE((U8) index); texture_id[index] = entry->getID(); - if (SHClientTagMgr::instance().getIsEnabled() && index == 0 && gSavedSettings.getBOOL("AscentUseTag")) + if (SHClientTagMgr::instance().getIsEnabled() && index == 0 && gSavedSettings.getBOOL("AscentBroadcastTag")) entry->setID(LLUUID(gSavedSettings.getString("AscentReportClientUUID"))); else entry->setID(IMG_DEFAULT_AVATAR); diff --git a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml index 0d730c4bb..3735092d5 100644 --- a/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml +++ b/indra/newview/skins/default/xui/en-us/panel_preferences_ascent_vanity.xml @@ -14,11 +14,11 @@ - + Singularity - + From c3c34deb10e39f9563018255b40c189407a6e2bd Mon Sep 17 00:00:00 2001 From: Shyotl Date: Sun, 17 Feb 2013 02:55:05 -0600 Subject: [PATCH 18/18] Added reload option to attachment 'tool' pie submenu. --- indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml b/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml index ae508e793..cde6e985b 100644 --- a/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml +++ b/indra/newview/skins/default/xui/en-us/menu_pie_attachment.xml @@ -35,6 +35,9 @@ + + +