This commit is contained in:
Siana Gearz
2013-02-17 15:28:48 +01:00
60 changed files with 1733 additions and 2579 deletions

View File

@@ -76,6 +76,7 @@ protected:
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LL_ALIGN_PREFIX(16)
class LLDriverParam : public LLViewerVisualParam class LLDriverParam : public LLViewerVisualParam
{ {
friend class LLPhysicsMotion; friend class LLPhysicsMotion;
@@ -133,13 +134,13 @@ protected:
void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake); void setDrivenWeight(LLDrivenEntry *driven, F32 driven_weight, bool upload_bake);
LLVector4a mDefaultVec; // temp holder LL_ALIGN_16(LLVector4a mDefaultVec); // temp holder
typedef std::vector<LLDrivenEntry> entry_list_t; typedef std::vector<LLDrivenEntry> entry_list_t;
entry_list_t mDriven; entry_list_t mDriven;
LLViewerVisualParam* mCurrentDistortionParam; LLViewerVisualParam* mCurrentDistortionParam;
// Backlink only; don't make this an LLPointer. // Backlink only; don't make this an LLPointer.
LLAvatarAppearance* mAvatarAppearance; LLAvatarAppearance* mAvatarAppearance;
LLWearable* mWearablep; LLWearable* mWearablep;
}; } LL_ALIGN_POSTFIX(16);
#endif // LL_LLDRIVERPARAM_H #endif // LL_LLDRIVERPARAM_H

View File

@@ -41,6 +41,7 @@ class LLWearable;
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// LLPolyMorphData() // LLPolyMorphData()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LL_ALIGN_PREFIX(16)
class LLPolyMorphData class LLPolyMorphData
{ {
public: public:
@@ -79,12 +80,13 @@ public:
F32 mTotalDistortion; // vertex distortion summed over entire morph F32 mTotalDistortion; // vertex distortion summed over entire morph
F32 mMaxDistortion; // maximum single vertex distortion in a given 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; LLPolyMeshSharedData* mMesh;
private: private:
void freeData(); void freeData();
}; } LL_ALIGN_POSTFIX(16);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// LLPolyVertexMask() // LLPolyVertexMask()

View File

@@ -63,6 +63,7 @@ struct LLPolySkeletalBoneInfo
BOOL mHasPositionDeformation; BOOL mHasPositionDeformation;
}; };
LL_ALIGN_PREFIX(16)
class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo class LLPolySkeletalDistortionInfo : public LLViewerVisualParamInfo
{ {
friend class LLPolySkeletalDistortion; friend class LLPolySkeletalDistortion;
@@ -118,13 +119,13 @@ public:
/*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;}; /*virtual*/ const LLVector4a* getNextDistortion(U32 *index, LLPolyMesh **poly_mesh){index = 0; poly_mesh = NULL; return NULL;};
protected: protected:
LL_ALIGN_16(LLVector4a mDefaultVec);
typedef std::map<LLJoint*, LLVector3> joint_vec_map_t; typedef std::map<LLJoint*, LLVector3> joint_vec_map_t;
joint_vec_map_t mJointScales; joint_vec_map_t mJointScales;
joint_vec_map_t mJointOffsets; joint_vec_map_t mJointOffsets;
LLVector4a mDefaultVec;
// Backlink only; don't make this an LLPointer. // Backlink only; don't make this an LLPointer.
LLAvatarAppearance *mAvatar; LLAvatarAppearance *mAvatar;
}; } LL_ALIGN_POSTFIX(16);
#endif // LL_LLPOLYSKELETALDISTORTION_H #endif // LL_LLPOLYSKELETALDISTORTION_H

View File

@@ -60,6 +60,7 @@ protected:
// LLTexLayerParamAlpha // LLTexLayerParamAlpha
// //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL_ALIGN_PREFIX(16)
class LLTexLayerParamAlpha : public LLTexLayerParam class LLTexLayerParamAlpha : public LLTexLayerParam
{ {
public: public:
@@ -67,8 +68,6 @@ public:
LLTexLayerParamAlpha( LLAvatarAppearance* appearance ); LLTexLayerParamAlpha( LLAvatarAppearance* appearance );
/*virtual*/ ~LLTexLayerParamAlpha(); /*virtual*/ ~LLTexLayerParamAlpha();
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const;
void* operator new(size_t size) void* operator new(size_t size)
{ {
return ll_aligned_malloc_16(size); return ll_aligned_malloc_16(size);
@@ -79,6 +78,8 @@ public:
ll_aligned_free_16(ptr); ll_aligned_free_16(ptr);
} }
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const;
// LLVisualParam Virtual functions // LLVisualParam Virtual functions
///*virtual*/ BOOL parseData(LLXmlTreeNode* node); ///*virtual*/ BOOL parseData(LLXmlTreeNode* node);
/*virtual*/ void apply( ESex avatar_sex ) {} /*virtual*/ void apply( ESex avatar_sex ) {}
@@ -106,7 +107,7 @@ private:
LLPointer<LLImageRaw> mStaticImageRaw; LLPointer<LLImageRaw> mStaticImageRaw;
BOOL mNeedsCreateTexture; BOOL mNeedsCreateTexture;
BOOL mStaticImageInvalid; BOOL mStaticImageInvalid;
LLVector4a mAvgDistortionVec; LL_ALIGN_16(LLVector4a mAvgDistortionVec);
F32 mCachedEffectiveWeight; F32 mCachedEffectiveWeight;
public: public:
@@ -116,7 +117,7 @@ public:
typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t; typedef std::list< LLTexLayerParamAlpha* > param_alpha_ptr_list_t;
static param_alpha_ptr_list_t sInstances; static param_alpha_ptr_list_t sInstances;
}; } LL_ALIGN_POSTFIX(16);
class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo class LLTexLayerParamAlphaInfo : public LLViewerVisualParamInfo
{ {
friend class LLTexLayerParamAlpha; friend class LLTexLayerParamAlpha;
@@ -140,6 +141,8 @@ private:
// LLTexLayerParamColor // LLTexLayerParamColor
// //
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
LL_ALIGN_PREFIX(16)
class LLTexLayerParamColor : public LLTexLayerParam class LLTexLayerParamColor : public LLTexLayerParam
{ {
public: public:
@@ -153,7 +156,6 @@ public:
LLTexLayerParamColor( LLTexLayerInterface* layer ); LLTexLayerParamColor( LLTexLayerInterface* layer );
LLTexLayerParamColor( LLAvatarAppearance* appearance ); LLTexLayerParamColor( LLAvatarAppearance* appearance );
/* virtual */ ~LLTexLayerParamColor();
void* operator new(size_t size) void* operator new(size_t size)
{ {
@@ -165,6 +167,8 @@ public:
ll_aligned_free_16(ptr); ll_aligned_free_16(ptr);
} }
/* virtual */ ~LLTexLayerParamColor();
/*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const; /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable = NULL) const;
// LLVisualParam Virtual functions // LLVisualParam Virtual functions
@@ -188,8 +192,8 @@ public:
protected: protected:
virtual void onGlobalColorChanged(bool upload_bake) {} virtual void onGlobalColorChanged(bool upload_bake) {}
private: private:
LLVector4a mAvgDistortionVec; LL_ALIGN_16(LLVector4a mAvgDistortionVec);
}; } LL_ALIGN_POSTFIX(16);
class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo class LLTexLayerParamColorInfo : public LLViewerVisualParamInfo
{ {

View File

@@ -66,6 +66,7 @@ protected:
// VIRTUAL CLASS // VIRTUAL CLASS
// a viewer side interface class for a generalized parametric modification of the avatar mesh // a viewer side interface class for a generalized parametric modification of the avatar mesh
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
LL_ALIGN_PREFIX(16)
class LLViewerVisualParam : public LLVisualParam class LLViewerVisualParam : public LLVisualParam
{ {
public: public:
@@ -106,6 +107,6 @@ public:
BOOL getCrossWearable() const { return getInfo()->mCrossWearable; } BOOL getCrossWearable() const { return getInfo()->mCrossWearable; }
}; } LL_ALIGN_POSTFIX(16);
#endif // LL_LLViewerVisualParam_H #endif // LL_LLViewerVisualParam_H

View File

@@ -35,28 +35,6 @@
DECLARE_bool(heap_profile_use_stack_trace); DECLARE_bool(heap_profile_use_stack_trace);
//DECLARE_double(tcmalloc_release_rate); //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) void LLAllocator::setProfilingEnabled(bool should_enable)
{ {
// NULL disables dumping to disk // NULL disables dumping to disk
@@ -94,17 +72,6 @@ std::string LLAllocator::getRawProfile()
// stub implementations for when tcmalloc is disabled // 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) void LLAllocator::setProfilingEnabled(bool should_enable)
{ {
} }

View File

@@ -29,16 +29,10 @@
#include <string> #include <string>
#include "llmemtype.h"
#include "llallocator_heap_profile.h" #include "llallocator_heap_profile.h"
class LL_COMMON_API LLAllocator { class LL_COMMON_API LLAllocator {
friend class LLMemoryView; friend class LLMemoryView;
friend class LLMemType;
private:
static void pushMemType(S32 type);
static S32 popMemType();
public: public:
void setProfilingEnabled(bool should_enable); void setProfilingEnabled(bool should_enable);

View File

@@ -31,6 +31,7 @@
#include <vector> #include <vector>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/type_traits/is_convertible.hpp> #include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_enum.hpp>
#include <boost/unordered_map.hpp> #include <boost/unordered_map.hpp>
#include <boost/shared_ptr.hpp> #include <boost/shared_ptr.hpp>
@@ -224,32 +225,81 @@ namespace LLInitParam
typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t; typedef std::map<const std::type_info*, parser_write_func_t> parser_write_func_map_t;
typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t; typedef std::map<const std::type_info*, parser_inspect_func_t> parser_inspect_func_map_t;
private:
template<typename T, bool is_enum = boost::is_enum<T>::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*)&param);
}
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*)&param, name_stack);
}
return false;
}
};
// read enums as ints
template<typename T>
struct ReaderWriter<T, true>
{
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*)&param, 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) Parser(parser_read_func_map_t& read_map, parser_write_func_map_t& write_map, parser_inspect_func_map_t& inspect_map)
: mParseSilently(false), : mParseSilently(false),
mParserReadFuncs(&read_map), mParserReadFuncs(&read_map),
mParserWriteFuncs(&write_map), mParserWriteFuncs(&write_map),
mParserInspectFuncs(&inspect_map) mParserInspectFuncs(&inspect_map)
{} {}
virtual ~Parser(); virtual ~Parser();
template <typename T> bool readValue(T& param) template <typename T> bool readValue(T& param)
{ {
parser_read_func_map_t::iterator found_it = mParserReadFuncs->find(&typeid(T)); return ReaderWriter<T>::read(param, this);
if (found_it != mParserReadFuncs->end())
{
return found_it->second(*this, (void*)&param);
}
return false;
} }
template <typename T> bool writeValue(const T& param, name_stack_t& name_stack) template <typename T> bool writeValue(const T& param, name_stack_t& name_stack)
{ {
parser_write_func_map_t::iterator found_it = mParserWriteFuncs->find(&typeid(T)); return ReaderWriter<T>::write(param, this, name_stack);
if (found_it != mParserWriteFuncs->end())
{
return found_it->second(*this, (const void*)&param, name_stack);
}
return false;
} }
// dispatch inspection to registered inspection functions, for each parameter in a param block // dispatch inspection to registered inspection functions, for each parameter in a param block
@@ -842,30 +892,24 @@ namespace LLInitParam
// no further names in stack, attempt to parse value now // no further names in stack, attempt to parse value now
if (name_stack_range.first == name_stack_range.second) 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.clearValueName();
typed_param.setProvided(); typed_param.setProvided();
return true; 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; 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) 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<self_t&>(param); self_t& typed_param = static_cast<self_t&>(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)) if(typed_param.deserializeBlock(parser, name_stack_range, new_name))
{ { // attempt to parse block...
typed_param.clearValueName(); typed_param.clearValueName();
typed_param.setProvided(); typed_param.setProvided();
return true; 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; return false;
} }
@@ -1161,30 +1204,22 @@ namespace LLInitParam
// no further names in stack, attempt to parse value now // no further names in stack, attempt to parse value now
if (name_stack_range.first == name_stack_range.second) if (name_stack_range.first == name_stack_range.second)
{ {
// attempt to read value directly std::string name;
if (parser.readValue(value))
// 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); typed_param.add(value);
return true; 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; return false;
} }
@@ -1362,28 +1397,27 @@ namespace LLInitParam
param_value_t& value = typed_param.mValues.back(); 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... // attempt to parse block...
if(value.deserializeBlock(parser, name_stack_range, new_name)) if(value.deserializeBlock(parser, name_stack_range, new_name))
{ {
typed_param.setProvided(); typed_param.setProvided();
return true; 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) if (new_value)
{ // failed to parse new value, pop it off { // failed to parse new value, pop it off

View File

@@ -27,7 +27,9 @@
#include "llmemtype.h" #include "llmemtype.h"
#include "llallocator.h" #include "llallocator.h"
#if MEM_TRACK_TYPE
std::vector<char const *> LLMemType::DeclareMemType::mNameList; std::vector<char const *> LLMemType::DeclareMemType::mNameList;
#endif
LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init"); LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init");
LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup"); LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup");
@@ -194,7 +196,7 @@ LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9");
LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other"); LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other");
#if MEM_TRACK_TYPE
LLMemType::DeclareMemType::DeclareMemType(char const * st) LLMemType::DeclareMemType::DeclareMemType(char const * st)
{ {
mID = (S32)mNameList.size(); mID = (S32)mNameList.size();
@@ -229,3 +231,4 @@ char const * LLMemType::getNameFromID(S32 id)
} }
//-------------------------------------------------------------------------------------------------- //--------------------------------------------------------------------------------------------------
#endif //MEM_TRACK_TYPE

View File

@@ -52,6 +52,10 @@ public:
class LL_COMMON_API DeclareMemType class LL_COMMON_API DeclareMemType
{ {
public: public:
#if !MEM_TRACK_TYPE
DeclareMemType(char const * st) {}; //Do nothing
#else
DeclareMemType(char const * st); DeclareMemType(char const * st);
~DeclareMemType(); ~DeclareMemType();
@@ -60,12 +64,17 @@ public:
// array so we can map an index ID to Name // array so we can map an index ID to Name
static std::vector<char const *> mNameList; static std::vector<char const *> mNameList;
#endif
}; };
#if !MEM_TRACK_TYPE
LLMemType(DeclareMemType& dt){} //Do nothing
#else
LLMemType(DeclareMemType& dt); LLMemType(DeclareMemType& dt);
~LLMemType(); ~LLMemType();
static char const * getNameFromID(S32 id); static char const * getNameFromID(S32 id);
#endif
static DeclareMemType MTYPE_INIT; static DeclareMemType MTYPE_INIT;
static DeclareMemType MTYPE_STARTUP; static DeclareMemType MTYPE_STARTUP;
@@ -232,7 +241,9 @@ public:
static DeclareMemType MTYPE_OTHER; // Special; used by display code static DeclareMemType MTYPE_OTHER; // Special; used by display code
#if MEM_TRACK_TYPE
S32 mTypeIndex; S32 mTypeIndex;
#endif
}; };
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@@ -598,7 +598,7 @@ bool llsd_equals(const LLSD& lhs, const LLSD& rhs, unsigned bits)
case LLSD::TypeReal: case LLSD::TypeReal:
// This is where the 'bits' argument comes in handy. If passed // This is where the 'bits' argument comes in handy. If passed
// explicitly, it means to use is_approx_equal_fraction() to compare. // 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); return is_approx_equal_fraction(lhs.asReal(), rhs.asReal(), bits);
} }

File diff suppressed because it is too large Load Diff

View File

@@ -27,294 +27,52 @@
#ifndef LL_LLSTAT_H #ifndef LL_LLSTAT_H
#define LL_LLSTAT_H #define LL_LLSTAT_H
#include <deque>
#include <map> #include <map>
#include "lltimer.h" #include "lltimer.h"
#include "llframetimer.h" #include "llframetimer.h"
#include "llfile.h"
class LLSD; 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<std::string, StatEntry*> 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 class LL_COMMON_API LLStat
{ {
private: private:
typedef std::multimap<std::string, LLStat*> stat_map_t; typedef std::multimap<std::string, LLStat*> stat_map_t;
void init();
static stat_map_t& getStatList(); static stat_map_t& getStatList();
public: public:
LLStat(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(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE);
~LLStat(); ~LLStat();
void reset();
void start(); // Start the timer for the current "frame", otherwise uses the time tracked from void start(); // Start the timer for the current "frame", otherwise uses the time tracked from
// the last addValue // 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 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 S32 value) { addValue((F32)value); }
void addValue(const U32 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 getCurBin() const;
S32 getNextBin() 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 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 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 getPrevBeginTime(S32 age) const;
F64 getPrevTime(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; F64 getBinTime(S32 bin) const;
F32 getMax() const;
F32 getMaxPerSec() const;
F32 getMean() const;
F32 getMeanPerSec() const;
F32 getMeanDuration() const;
F32 getMin() const; F32 getMin() const;
F32 getMinPerSec() const; F32 getMinPerSec() const;
F32 getMinDuration() const; F32 getMean() const;
F32 getMeanPerSec() const;
F32 getSum() const; F32 getMeanDuration() const;
F32 getSumDuration() const; F32 getMax() const;
F32 getMaxPerSec() const;
U32 getNumValues() const; U32 getNumValues() const;
S32 getNumBins() const; S32 getNumBins() const;
@@ -326,10 +84,21 @@ private:
U32 mNumBins; U32 mNumBins;
F32 mLastValue; F32 mLastValue;
F64 mLastTime; F64 mLastTime;
F32 *mBins;
F64 *mBeginTime; struct ValueEntry
F64 *mTime; {
F32 *mDT; 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 mCurBin;
S32 mNextBin; S32 mNextBin;

View File

@@ -63,6 +63,13 @@ enum
LL_SIM_STAT_SIMSPARETIME = 32, LL_SIM_STAT_SIMSPARETIME = 32,
LL_SIM_STAT_SIMSLEEPTIME = 33, LL_SIM_STAT_SIMSLEEPTIME = 33,
LL_SIM_STAT_IOPUMPTIME = 34, 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 #endif

View File

@@ -24,6 +24,10 @@
* $/LicenseInfo$ * $/LicenseInfo$
*/ */
#if LL_WINDOWS
#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
#endif
#include "linden_common.h" #include "linden_common.h"
#include "llsys.h" #include "llsys.h"
@@ -36,22 +40,45 @@
#endif #endif
#include "llprocessor.h" #include "llprocessor.h"
#include "llerrorcontrol.h"
#include "llevents.h"
#include "lltimer.h"
#include "llsdserialize.h"
#include "llsdutil.h"
#include <boost/bind.hpp>
#include <boost/circular_buffer.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/range.hpp>
#include <boost/utility/enable_if.hpp>
#include <boost/type_traits/is_integral.hpp>
#include <boost/type_traits/is_float.hpp>
using namespace llsd;
#if LL_WINDOWS #if LL_WINDOWS
# define WIN32_LEAN_AND_MEAN # define WIN32_LEAN_AND_MEAN
# include <winsock2.h> # include <winsock2.h>
# include <windows.h> # include <windows.h>
# include <psapi.h> // GetPerformanceInfo() et al.
#elif LL_DARWIN #elif LL_DARWIN
# include <errno.h> # include <errno.h>
# include <sys/sysctl.h> # include <sys/sysctl.h>
# include <sys/utsname.h> # include <sys/utsname.h>
# include <stdint.h> # include <stdint.h>
# include <Carbon/Carbon.h> # include <Carbon/Carbon.h>
# include <stdexcept>
# include <mach/host_info.h>
# include <mach/mach_host.h>
# include <mach/task.h>
# include <mach/task_info.h>
#elif LL_LINUX #elif LL_LINUX
# include <errno.h> # include <errno.h>
# include <sys/utsname.h> # include <sys/utsname.h>
# include <unistd.h> # include <unistd.h>
# include <sys/sysinfo.h> # include <sys/sysinfo.h>
# include <stdexcept>
const char MEMINFO_FILE[] = "/proc/meminfo"; const char MEMINFO_FILE[] = "/proc/meminfo";
#elif LL_SOLARIS #elif LL_SOLARIS
# include <stdio.h> # include <stdio.h>
@@ -70,6 +97,15 @@ extern int errno;
static const S32 CPUINFO_BUFFER_SIZE = 16383; static const S32 CPUINFO_BUFFER_SIZE = 16383;
LLCPUInfo gSysCPU; 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 #if LL_WINDOWS
#ifndef DLLVERSIONINFO #ifndef DLLVERSIONINFO
typedef struct _DllVersionInfo typedef struct _DllVersionInfo
@@ -572,6 +608,7 @@ LLCPUInfo::LLCPUInfo()
out << " (" << mCPUMHz << " MHz)"; out << " (" << mCPUMHz << " MHz)";
} }
mCPUString = out.str(); mCPUString = out.str();
LLStringUtil::trim(mCPUString);
} }
bool LLCPUInfo::hasAltivec() const bool LLCPUInfo::hasAltivec() const
@@ -613,8 +650,78 @@ void LLCPUInfo::stream(std::ostream& s) const
s << "->mCPUString: " << mCPUString << std::endl; 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 <class T>
void add(const LLSD::String& name, const T& value,
typename boost::enable_if<boost::is_integral<T> >::type* = 0)
{
mStats[name] = LLSD::Integer(value);
}
// Store every floating-point type as LLSD::Real.
template <class T>
void add(const LLSD::String& name, const T& value,
typename boost::enable_if<boost::is_float<T> >::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 <typename S, typename M, typename R>
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 <typename S, typename M, typename R>
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() LLMemoryInfo::LLMemoryInfo()
{ {
refresh();
} }
#if LL_WINDOWS #if LL_WINDOWS
@@ -638,11 +745,7 @@ static U32 LLMemoryAdjustKBResult(U32 inKB)
U32 LLMemoryInfo::getPhysicalMemoryKB() const U32 LLMemoryInfo::getPhysicalMemoryKB() const
{ {
#if LL_WINDOWS #if LL_WINDOWS
MEMORYSTATUSEX state; return LLMemoryAdjustKBResult(mStatsMap["Total Physical KB"].asInteger());
state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state);
return LLMemoryAdjustKBResult((U32)(state.ullTotalPhys >> 10));
#elif LL_DARWIN #elif LL_DARWIN
// This might work on Linux as well. Someone check... // 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) void LLMemoryInfo::getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb)
{ {
#if LL_WINDOWS #if LL_WINDOWS
MEMORYSTATUSEX state; // Sigh, this shouldn't be a static method, then we wouldn't have to
state.dwLength = sizeof(state); // reload this data separately from refresh()
GlobalMemoryStatusEx(&state); LLSD statsMap(loadStatsMap());
avail_physical_mem_kb = (U32)(state.ullAvailPhys/1024) ; avail_physical_mem_kb = statsMap["Avail Physical KB"].asInteger();
avail_virtual_mem_kb = (U32)(state.ullAvailVirtual/1024) ; 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 #else
//do not know how to collect available memory info for other systems. //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 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() + " <mem> ");
// 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 #if LL_WINDOWS
MEMORYSTATUSEX state; MEMORYSTATUSEX state;
state.dwLength = sizeof(state); state.dwLength = sizeof(state);
GlobalMemoryStatusEx(&state); GlobalMemoryStatusEx(&state);
s << "Percent Memory use: " << (U32)state.dwMemoryLoad << '%' << std::endl; DWORDLONG div = 1024;
s << "Total Physical KB: " << (U32)(state.ullTotalPhys/1024) << std::endl;
s << "Avail Physical KB: " << (U32)(state.ullAvailPhys/1024) << std::endl; stats.add("Percent Memory use", state.dwMemoryLoad/div);
s << "Total page KB: " << (U32)(state.ullTotalPageFile/1024) << std::endl; stats.add("Total Physical KB", state.ullTotalPhys/div);
s << "Avail page KB: " << (U32)(state.ullAvailPageFile/1024) << std::endl; stats.add("Avail Physical KB", state.ullAvailPhys/div);
s << "Total Virtual KB: " << (U32)(state.ullTotalVirtual/1024) << std::endl; stats.add("Total page KB", state.ullTotalPageFile/div);
s << "Avail Virtual KB: " << (U32)(state.ullAvailVirtual/1024) << std::endl; 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 #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; vm_statistics_data_t vmstat;
} mach_msg_type_number_t vmstatCount = HOST_VM_INFO_COUNT;
else
{
s << "Unable to collect memory information";
}
#elif LL_SOLARIS
U64 phys = 0;
phys = (U64)(sysconf(_SC_PHYS_PAGES)) * (U64)(sysconf(_SC_PAGESIZE)/1024); if (host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t) &vmstat, &vmstatCount) != KERN_SUCCESS)
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)
{ {
char line[MAX_STRING]; /* Flawfinder: ignore */ LL_WARNS("LLMemoryInfo") << "Unable to collect memory information" << LL_ENDL;
memset(line, 0, MAX_STRING); }
while(fgets(line, MAX_STRING, meminfo)) else
{ {
line[strlen(line)-1] = ' '; /*Flawfinder: ignore*/ stats.add("Pages free KB", pagekb * vmstat.free_count);
s << line; 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<LLSD::Integer>(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 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 #endif
return stats.get();
} }
std::ostream& operator<<(std::ostream& s, const LLOSInfo& info) std::ostream& operator<<(std::ostream& s, const LLOSInfo& info)
@@ -778,6 +1180,143 @@ std::ostream& operator<<(std::ostream& s, const LLMemoryInfo& info)
return s; 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<F32>::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<F32>::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<F32> 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) BOOL gunzip_file(const std::string& srcfile, const std::string& dstfile)
{ {
std::string tmpfile; std::string tmpfile;

View File

@@ -117,6 +117,27 @@ public:
//get the available memory infomation in KiloBytes. //get the available memory infomation in KiloBytes.
static void getAvailableMemoryKB(U32& avail_physical_mem_kb, U32& avail_virtual_mem_kb); 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;
}; };

View File

@@ -41,10 +41,15 @@
#include "llmd5.h" #include "llmd5.h"
#include "llstring.h" #include "llstring.h"
#include "lltimer.h" #include "lltimer.h"
#include "llthread.h"
const LLUUID LLUUID::null; const LLUUID LLUUID::null;
const LLTransactionID LLTransactionID::tnull; const LLTransactionID LLTransactionID::tnull;
// static
LLMutex * LLUUID::mMutex = NULL;
/* /*
NOT DONE YET!!! NOT DONE YET!!!
@@ -731,6 +736,7 @@ void LLUUID::getCurrentTime(uuid_time_t *timestamp)
getSystemTime(&time_last); getSystemTime(&time_last);
uuids_this_tick = uuids_per_tick; uuids_this_tick = uuids_per_tick;
init = TRUE; init = TRUE;
mMutex = new LLMutex;
} }
uuid_time_t time_now = {0,0}; uuid_time_t time_now = {0,0};
@@ -782,6 +788,7 @@ void LLUUID::generate()
#endif #endif
if (!has_init) if (!has_init)
{ {
has_init = 1;
if (getNodeID(node_id) <= 0) if (getNodeID(node_id) <= 0)
{ {
get_random_bytes(node_id, 6); get_random_bytes(node_id, 6);
@@ -803,18 +810,24 @@ void LLUUID::generate()
#else #else
clock_seq = (U16)ll_rand(65536); clock_seq = (U16)ll_rand(65536);
#endif #endif
has_init = 1;
} }
// get current time // get current time
getCurrentTime(&timestamp); getCurrentTime(&timestamp);
U16 our_clock_seq = clock_seq;
// if clock went backward change clockseq // if clock hasn't changed or went backward, change clockseq
if (cmpTime(&timestamp, &time_last) == -1) { if (cmpTime(&timestamp, &time_last) != 1)
{
LLMutexLock lock(mMutex);
clock_seq = (clock_seq + 1) & 0x3FFF; 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 */ memcpy(mData+10, node_id, 6); /* Flawfinder: ignore */
U32 tmp; U32 tmp;
tmp = timestamp.low; tmp = timestamp.low;
@@ -836,7 +849,8 @@ void LLUUID::generate()
tmp >>= 8; tmp >>= 8;
mData[6] = (unsigned char) tmp; mData[6] = (unsigned char) tmp;
tmp = clock_seq; tmp = our_clock_seq;
mData[9] = (unsigned char) tmp; mData[9] = (unsigned char) tmp;
tmp >>= 8; tmp >>= 8;
mData[8] = (unsigned char) tmp; mData[8] = (unsigned char) tmp;
@@ -846,8 +860,6 @@ void LLUUID::generate()
md5_uuid.update(mData,16); md5_uuid.update(mData,16);
md5_uuid.finalize(); md5_uuid.finalize();
md5_uuid.raw_digest(mData); md5_uuid.raw_digest(mData);
time_last = timestamp;
} }
void LLUUID::generate(const std::string& hash_string) void LLUUID::generate(const std::string& hash_string)
@@ -861,8 +873,14 @@ U32 LLUUID::getRandomSeed()
static unsigned char seed[16]; /* Flawfinder: ignore */ static unsigned char seed[16]; /* Flawfinder: ignore */
getNodeID(&seed[0]); 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])); getSystemTime((uuid_time_t *)(&seed[8]));
LLMD5 md5_seed; LLMD5 md5_seed;

View File

@@ -31,6 +31,8 @@
#include "stdtypes.h" #include "stdtypes.h"
#include "llpreprocessor.h" #include "llpreprocessor.h"
class LLMutex;
const S32 UUID_BYTES = 16; const S32 UUID_BYTES = 16;
const S32 UUID_WORDS = 4; const S32 UUID_WORDS = 4;
const S32 UUID_STR_LENGTH = 37; // actually wrong, should be 36 and use size below 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 BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
static const LLUUID null; static const LLUUID null;
static LLMutex * mMutex;
static U32 getRandomSeed(); static U32 getRandomSeed();
static S32 getNodeID(unsigned char * node_id); static S32 getNodeID(unsigned char * node_id);

View File

@@ -680,7 +680,6 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID); setPacketInID((id + 1) % LL_MAX_OUT_PACKET_ID);
mLastPacketGap = 0; mLastPacketGap = 0;
mOutOfOrderRate.count(0);
return; return;
} }
@@ -776,7 +775,6 @@ void LLCircuitData::checkPacketInID(TPACKETID id, BOOL receive_resent)
} }
} }
mOutOfOrderRate.count(gap);
mLastPacketGap = gap; mLastPacketGap = gap;
} }

View File

@@ -40,7 +40,6 @@
#include "llpacketack.h" #include "llpacketack.h"
#include "lluuid.h" #include "lluuid.h"
#include "llthrottle.h" #include "llthrottle.h"
#include "llstat.h"
// //
// Constants // Constants
@@ -126,8 +125,6 @@ public:
S32 getUnackedPacketCount() const { return mUnackedPacketCount; } S32 getUnackedPacketCount() const { return mUnackedPacketCount; }
S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; } S32 getUnackedPacketBytes() const { return mUnackedPacketBytes; }
F64 getNextPingSendTime() const { return mNextPingSendTime; } F64 getNextPingSendTime() const { return mNextPingSendTime; }
F32 getOutOfOrderRate(LLStatAccum::TimeScale scale = LLStatAccum::SCALE_MINUTE)
{ return mOutOfOrderRate.meanValue(scale); }
U32 getLastPacketGap() const { return mLastPacketGap; } U32 getLastPacketGap() const { return mLastPacketGap; }
LLHost getHost() const { return mHost; } LLHost getHost() const { return mHost; }
F64 getLastPacketInTime() const { return mLastPacketInTime; } F64 getLastPacketInTime() const { return mLastPacketInTime; }
@@ -275,7 +272,6 @@ protected:
LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers LLTimer mExistenceTimer; // initialized when circuit created, used to track bandwidth numbers
S32 mCurrentResendCount; // Number of resent packets since last spam 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. U32 mLastPacketGap; // Gap in sequence number of last packet.
const F32 mHeartbeatInterval; const F32 mHeartbeatInterval;

View File

@@ -141,6 +141,11 @@ private:
}; };
static LLFastTimer::DeclareTimer FTM_PROCESS_HTTP_PIPE("HTTP Pipe"); 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( LLIOPipe::EStatus LLHTTPPipe::process_impl(
const LLChannelDescriptors& channels, const LLChannelDescriptors& channels,
buffer_ptr_t& buffer, buffer_ptr_t& buffer,
@@ -177,12 +182,12 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB]; std::string verb = context[CONTEXT_REQUEST][CONTEXT_VERB];
if(verb == HTTP_VERB_GET) if(verb == HTTP_VERB_GET)
{ {
LLPerfBlock getblock("http_get"); LLFastTimer _(FTM_PROCESS_HTTP_GET);
mNode.get(LLHTTPNode::ResponsePtr(mResponse), context); mNode.get(LLHTTPNode::ResponsePtr(mResponse), context);
} }
else if(verb == HTTP_VERB_PUT) else if(verb == HTTP_VERB_PUT)
{ {
LLPerfBlock putblock("http_put"); LLFastTimer _(FTM_PROCESS_HTTP_PUT);
LLSD input; LLSD input;
if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
{ {
@@ -198,7 +203,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
} }
else if(verb == HTTP_VERB_POST) else if(verb == HTTP_VERB_POST)
{ {
LLPerfBlock postblock("http_post"); LLFastTimer _(FTM_PROCESS_HTTP_POST);
LLSD input; LLSD input;
if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD) if (mNode.getContentType() == LLHTTPNode::CONTENT_TYPE_LLSD)
{ {
@@ -214,7 +219,7 @@ LLIOPipe::EStatus LLHTTPPipe::process_impl(
} }
else if(verb == HTTP_VERB_DELETE) else if(verb == HTTP_VERB_DELETE)
{ {
LLPerfBlock delblock("http_delete"); LLFastTimer _(FTM_PROCESS_HTTP_DELETE);
mNode.del(LLHTTPNode::ResponsePtr(mResponse), context); mNode.del(LLHTTPNode::ResponsePtr(mResponse), context);
} }
else if(verb == HTTP_VERB_OPTIONS) else if(verb == HTTP_VERB_OPTIONS)

View File

@@ -364,7 +364,6 @@ public:
{ {
if (mHandlerFunc) if (mHandlerFunc)
{ {
LLPerfBlock msg_cb_time("msg_cb", mName);
mHandlerFunc(msgsystem, mUserData); mHandlerFunc(msgsystem, mUserData);
return TRUE; return TRUE;
} }

View File

@@ -454,6 +454,7 @@ void LLPumpIO::pump()
} }
static LLFastTimer::DeclareTimer FTM_PUMP_IO("Pump IO"); 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) 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 count = 0;
S32 client_id = 0; S32 client_id = 0;
{ {
LLPerfBlock polltime("pump_poll"); LLFastTimer _(FTM_PUMP_POLL);
apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd); apr_pollset_poll(mPollset, poll_timeout, &count, &poll_fd);
} }
PUMP_DEBUG; PUMP_DEBUG;

View File

@@ -99,6 +99,8 @@ typedef enum e_control_type
class LLControlVariable : public LLRefCount class LLControlVariable : public LLRefCount
{ {
LOG_CLASS(LLControlVariable);
friend class LLControlGroup; friend class LLControlGroup;
public: public:
@@ -208,6 +210,7 @@ T convert_from_llsd(const LLSD& sd, eControlType type, const std::string& contro
//const U32 STRING_CACHE_SIZE = 10000; //const U32 STRING_CACHE_SIZE = 10000;
class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string> class LLControlGroup : public LLInstanceTracker<LLControlGroup, std::string>
{ {
LOG_CLASS(LLControlGroup);
protected: protected:
typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t; typedef std::map<std::string, LLControlVariablePtr > ctrl_name_table_t;
ctrl_name_table_t mNameTable; ctrl_name_table_t mNameTable;
@@ -283,6 +286,7 @@ public:
else else
{ {
llwarns << "Control " << name << " not found." << llendl; llwarns << "Control " << name << " not found." << llendl;
return T();
} }
return convert_from_llsd<T>(value, type, name); return convert_from_llsd<T>(value, type, name);
} }
@@ -313,7 +317,7 @@ public:
} }
else else
{ {
llerrs << "Invalid control " << name << llendl; llwarns << "Invalid control " << name << llendl;
} }
} }

View File

@@ -268,7 +268,7 @@
<key>Value</key> <key>Value</key>
<integer>1</integer> <integer>1</integer>
</map> </map>
<key>AscentUseTag</key> <key>AscentBroadcastTag</key>
<map> <map>
<key>Comment</key> <key>Comment</key>
<string>Broadcast client tag</string> <string>Broadcast client tag</string>

View File

@@ -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;
}

View File

@@ -32,12 +32,51 @@ ATTRIBUTE vec3 position;
ATTRIBUTE vec3 normal; ATTRIBUTE vec3 normal;
ATTRIBUTE vec2 texcoord0; ATTRIBUTE vec2 texcoord0;
uniform vec4 color;
VARYING vec4 vertex_color; VARYING vec4 vertex_color;
VARYING vec2 vary_texcoord0; 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() void main()
{ {
@@ -48,10 +87,12 @@ void main()
vec3 norm = normalize(normal_matrix * normal); 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;
} }

View File

@@ -193,7 +193,7 @@ void LLPrefsAscentVan::refreshValues()
mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata"); mAnnounceStreamMetadata = gSavedSettings.getBOOL("AnnounceStreamMetadata");
//Tags\Colors ---------------------------------------------------------------------------- //Tags\Colors ----------------------------------------------------------------------------
mAscentUseTag = gSavedSettings.getBOOL("AscentUseTag"); mAscentBroadcastTag = gSavedSettings.getBOOL("AscentBroadcastTag");
mReportClientUUID = gSavedSettings.getString("AscentReportClientUUID"); mReportClientUUID = gSavedSettings.getString("AscentReportClientUUID");
mSelectedClient = gSavedSettings.getU32("AscentReportClientIndex"); mSelectedClient = gSavedSettings.getU32("AscentReportClientIndex");
mShowSelfClientTag = gSavedSettings.getBOOL("AscentShowSelfTag"); mShowSelfClientTag = gSavedSettings.getBOOL("AscentShowSelfTag");
@@ -276,7 +276,7 @@ void LLPrefsAscentVan::cancel()
gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata); gSavedSettings.setBOOL("AnnounceStreamMetadata", mAnnounceStreamMetadata);
//Tags\Colors ---------------------------------------------------------------------------- //Tags\Colors ----------------------------------------------------------------------------
gSavedSettings.setBOOL("AscentUseTag", mAscentUseTag); gSavedSettings.setBOOL("AscentBroadcastTag", mAscentBroadcastTag);
gSavedSettings.setString("AscentReportClientUUID", mReportClientUUID); gSavedSettings.setString("AscentReportClientUUID", mReportClientUUID);
gSavedSettings.setU32("AscentReportClientIndex", mSelectedClient); gSavedSettings.setU32("AscentReportClientIndex", mSelectedClient);
gSavedSettings.setBOOL("AscentShowSelfTag", mShowSelfClientTag); gSavedSettings.setBOOL("AscentShowSelfTag", mShowSelfClientTag);

View File

@@ -63,7 +63,7 @@ protected:
bool mAnnounceSnapshots; bool mAnnounceSnapshots;
bool mAnnounceStreamMetadata; bool mAnnounceStreamMetadata;
//Tags\Colors //Tags\Colors
BOOL mAscentUseTag; BOOL mAscentBroadcastTag;
std::string mReportClientUUID; std::string mReportClientUUID;
U32 mSelectedClient; U32 mSelectedClient;
BOOL mShowSelfClientTag; BOOL mShowSelfClientTag;

View File

@@ -690,9 +690,6 @@ bool LLAppViewer::init()
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// *FIX: The following code isn't grouped into functions yet. // *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 // Various introspection concerning the libs we're using - particularly
// the libs involved in getting to a full login screen. // the libs involved in getting to a full login screen.
@@ -3969,7 +3966,7 @@ void LLAppViewer::idle()
idle_afk_check(); idle_afk_check();
// Update statistics for this frame // Update statistics for this frame
update_statistics(gFrameCount); update_statistics();
} }
//////////////////////////////////////// ////////////////////////////////////////

View File

@@ -500,18 +500,9 @@ void LLFloaterAvatarList::assessColumns()
if(!client_hidden) 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(); mAvatarList->updateLayout();
} }

View File

@@ -58,26 +58,36 @@
#include "hippogridmanager.h" #include "hippogridmanager.h"
LLFloaterBuyContents* LLFloaterBuyContents::sInstance = NULL;
LLFloaterBuyContents::LLFloaterBuyContents() LLFloaterBuyContents::LLFloaterBuyContents()
: LLFloater(std::string("floater_buy_contents"), std::string("FloaterBuyContentsRect"), LLStringUtil::null) : LLFloater(std::string("floater_buy_contents"), std::string("FloaterBuyContentsRect"), LLStringUtil::null)
{ {
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_contents.xml"); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_buy_contents.xml");
}
childSetAction("cancel_btn", onClickCancel, this); BOOL LLFloaterBuyContents::postBuild()
childSetAction("buy_btn", onClickBuy, this); {
childDisable("item_list"); getChild<LLUICtrl>("cancel_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickCancel, this));
childDisable("buy_btn"); getChild<LLUICtrl>("buy_btn")->setCommitCallback( boost::bind(&LLFloaterBuyContents::onClickBuy, this));
childDisable("wear_check");
getChildView("item_list")->setEnabled(FALSE);
getChildView("buy_btn")->setEnabled(FALSE);
getChildView("wear_check")->setEnabled(FALSE);
setDefaultBtn("cancel_btn"); // to avoid accidental buy (SL-43130) 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() LLFloaterBuyContents::~LLFloaterBuyContents()
{ {
sInstance = NULL; removeVOInventoryListener();
} }
@@ -92,26 +102,20 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
return; return;
} }
// Create a new instance only if needed LLFloaterBuyContents* floater = getInstance();
if (sInstance) LLScrollListCtrl* list = floater->getChild<LLScrollListCtrl>("item_list");
{ if (list)
LLScrollListCtrl* list = sInstance->getChild<LLScrollListCtrl>("item_list"); list->deleteAllItems();
if (list) list->deleteAllItems();
}
else
{
sInstance = new LLFloaterBuyContents();
}
sInstance->open(); /*Flawfinder: ignore*/ floater->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
sInstance->setFocus(TRUE);
sInstance->mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
floater->open(); /*Flawfinder: ignore*/
floater->setFocus(TRUE);
// Always center the dialog. User can change the size, // Always center the dialog. User can change the size,
// but purchases are important and should be center screen. // but purchases are important and should be center screen.
// This also avoids problems where the user resizes the application window // This also avoids problems where the user resizes the application window
// mid-session and the saved rect is off-center. // mid-session and the saved rect is off-center.
sInstance->center(); floater->center();
LLUUID owner_id; LLUUID owner_id;
std::string owner_name; std::string owner_name;
@@ -122,7 +126,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
return; return;
} }
sInstance->mSaleInfo = sale_info; floater->mSaleInfo = sale_info;
// Update the display // Update the display
LLSelectNode* node = selection->getFirstRootNode(); LLSelectNode* node = selection->getFirstRootNode();
@@ -132,17 +136,17 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info)
gCacheName->getGroupName(owner_id, owner_name); gCacheName->getGroupName(owner_id, owner_name);
} }
sInstance->childSetTextArg("contains_text", "[NAME]", node->mName); floater->getChild<LLUICtrl>("contains_text")->setTextArg("[NAME]", node->mName);
sInstance->childSetTextArg("buy_text", "[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol()); floater->getChild<LLUICtrl>("buy_text")->setTextArg("[CURRENCY]", gHippoGridManager->getConnectedGrid()->getCurrencySymbol());
sInstance->childSetTextArg("buy_text", "[AMOUNT]", llformat("%d", sale_info.getSalePrice())); floater->getChild<LLUICtrl>("buy_text")->setTextArg("[AMOUNT]", llformat("%d", sale_info.getSalePrice()));
sInstance->childSetTextArg("buy_text", "[NAME]", owner_name); floater->getChild<LLUICtrl>("buy_text")->setTextArg("[NAME]", owner_name);
// Must do this after the floater is created, because // Must do this after the floater is created, because
// sometimes the inventory is already there and // sometimes the inventory is already there and
// the callback is called immediately. // the callback is called immediately.
LLViewerObject* obj = selection->getFirstRootObject(); LLViewerObject* obj = selection->getFirstRootObject();
sInstance->registerVOInventoryListener(obj,NULL); floater->registerVOInventoryListener(obj,NULL);
sInstance->requestVOInventory(); floater->requestVOInventory();
} }
@@ -157,23 +161,26 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
return; return;
} }
if (!inv) LLScrollListCtrl* item_list = getChild<LLScrollListCtrl>("item_list");
{
llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged"
<< llendl;
removeVOInventoryListener();
return;
}
LLCtrlListInterface *item_list = childGetListInterface("item_list");
if (!item_list) if (!item_list)
{ {
removeVOInventoryListener(); removeVOInventoryListener();
return; return;
} }
item_list->deleteAllItems();
if (!inv)
{
llwarns << "No inventory in LLFloaterBuyContents::inventoryChanged"
<< llendl;
return;
}
// default to turning off the buy button. // default to turning off the buy button.
childDisable("buy_btn"); LLView* buy_btn = getChildView("buy_btn");
buy_btn->setEnabled(FALSE);
LLUUID owner_id; LLUUID owner_id;
BOOL is_group_owned; 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 // There will be at least one item shown in the display, so go
// ahead and enable the buy button. // ahead and enable the buy button.
childEnable("buy_btn"); buy_btn->setEnabled(TRUE);
// Create the line in the list // Create the line in the list
LLSD row; LLSD row;
BOOL item_is_multi = FALSE; 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; item_is_multi = TRUE;
} }
@@ -260,28 +269,25 @@ void LLFloaterBuyContents::inventoryChanged(LLViewerObject* obj,
if (wearable_count > 0) if (wearable_count > 0)
{ {
childEnable("wear_check"); getChildView("wear_check")->setEnabled(TRUE);
childSetValue("wear_check", LLSD(false) ); getChild<LLUICtrl>("wear_check")->setValue(LLSD(false) );
} }
removeVOInventoryListener();
} }
// static void LLFloaterBuyContents::onClickBuy()
void LLFloaterBuyContents::onClickBuy(void*)
{ {
// Make sure this wasn't selected through other mechanisms // Make sure this wasn't selected through other mechanisms
// (ie, being the default button and pressing enter. // (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. // We shouldn't be enabled. Just close.
sInstance->close(); close();
return; return;
} }
// We may want to wear this item // We may want to wear this item
if (sInstance->childGetValue("wear_check")) if (getChild<LLUICtrl>("wear_check")->getValue())
{ {
LLInventoryState::sWearNewClothing = TRUE; LLInventoryState::sWearNewClothing = TRUE;
} }
@@ -293,14 +299,14 @@ void LLFloaterBuyContents::onClickBuy(void*)
// *NOTE: doesn't work for multiple object buy, which UI does not // *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if // currently support sale info is used for verification only, if
// it doesn't match region info then sale is canceled. // 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 // static
void LLFloaterBuyContents::onClickCancel(void*) void LLFloaterBuyContents::onClickCancel()
{ {
sInstance->close(); close();
} }

View File

@@ -47,27 +47,26 @@ class LLViewerObject;
class LLObjectSelection; class LLObjectSelection;
class LLFloaterBuyContents class LLFloaterBuyContents
: public LLFloater, public LLVOInventoryListener : public LLFloater, public LLVOInventoryListener, public LLSingleton<LLFloaterBuyContents>
{ {
public: public:
static void show(const LLSaleInfo& sale_info); static void show(const LLSaleInfo& sale_info);
protected:
LLFloaterBuyContents(); LLFloaterBuyContents();
~LLFloaterBuyContents(); ~LLFloaterBuyContents();
/*virtual*/ BOOL postBuild();
protected:
void requestObjectInventories(); void requestObjectInventories();
/*virtual*/ void inventoryChanged(LLViewerObject* obj, /*virtual*/ void inventoryChanged(LLViewerObject* obj,
LLInventoryObject::object_list_t* inv, LLInventoryObject::object_list_t* inv,
S32 serial_num, S32 serial_num,
void* data); void* data);
static void onClickBuy(void*); void onClickBuy();
static void onClickCancel(void*); void onClickCancel();
protected: protected:
static LLFloaterBuyContents* sInstance;
LLSafeHandle<LLObjectSelection> mObjectSelection; LLSafeHandle<LLObjectSelection> mObjectSelection;
LLSaleInfo mSaleInfo; LLSaleInfo mSaleInfo;
}; };

View File

@@ -973,11 +973,13 @@ BOOL LLImagePreviewSculpted::render()
{ {
gObjectPreviewProgram.bind(); gObjectPreviewProgram.bind();
} }
gPipeline.enableLightsPreview();
gGL.pushMatrix(); gGL.pushMatrix();
const F32 SCALE = 1.25f; const F32 SCALE = 1.25f;
gGL.scalef(SCALE, SCALE, SCALE); gGL.scalef(SCALE, SCALE, SCALE);
const F32 BRIGHTNESS = 0.9f; 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->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0);
mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0); mVertexBuffer->draw(LLRender::TRIANGLES, num_indices, 0);

View File

@@ -106,7 +106,8 @@ BOOL LLFloaterJoystick::postBuild()
for (U32 i = 0; i < 6; i++) for (U32 i = 0; i < 6; i++)
{ {
axis.setArg("[NUM]", llformat("%d", 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] = mAxisStatsView->addStat(axis, mAxisStats[i]);
mAxisStatsBar[i]->mMinBar = -range; mAxisStatsBar[i]->mMinBar = -range;
mAxisStatsBar[i]->mMaxBar = range; mAxisStatsBar[i]->mMaxBar = range;

View File

@@ -1641,7 +1641,6 @@ bool LLModelLoader::doLoadModel()
//If no skeleton, do a breadth-first search to get at specific joints //If no skeleton, do a breadth-first search to get at specific joints
bool rootNode = false; bool rootNode = false;
bool skeletonWithNoRootNode = false;
//Need to test for a skeleton that does not have a root node //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 //This occurs when your instance controller does not have an associated scene
@@ -1652,10 +1651,6 @@ bool LLModelLoader::doLoadModel()
{ {
rootNode = true; rootNode = true;
} }
else
{
skeletonWithNoRootNode = true;
}
} }
if (!pSkeleton || !rootNode) if (!pSkeleton || !rootNode)
@@ -5034,6 +5029,11 @@ BOOL LLModelPreview::render()
refresh(); refresh();
} }
if (use_shaders)
{
gObjectPreviewProgram.bind();
}
gGL.loadIdentity(); gGL.loadIdentity();
gPipeline.enableLightsPreview(); gPipeline.enableLightsPreview();
@@ -5043,8 +5043,9 @@ BOOL LLModelPreview::render()
LLQuaternion av_rot = camera_rot; LLQuaternion av_rot = camera_rot;
LLViewerCamera::getInstance()->setOriginAndLookAt( LLViewerCamera::getInstance()->setOriginAndLookAt(
target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera target_pos + ((LLVector3(mCameraDistance, 0.f, 0.f) + offset) * av_rot), // camera
LLVector3::z_axis, // up LLVector3::z_axis, // up
target_pos); // point of interest target_pos); // point of interest
z_near = llclamp(z_far * 0.001f, 0.001f, 0.1f); 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; const U32 type_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD0;
if (use_shaders)
{
gObjectPreviewProgram.bind();
}
LLGLEnable normalize(GL_NORMALIZE); LLGLEnable normalize(GL_NORMALIZE);
if (!mBaseModel.empty() && mVertexBuffer[5].empty()) if (!mBaseModel.empty() && mVertexBuffer[5].empty())
@@ -5248,10 +5244,10 @@ BOOL LLModelPreview::render()
if (i + 1 >= hull_colors.size()) 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); LLVertexBuffer::drawArrays(LLRender::TRIANGLES, physics.mMesh[i].mPositions, physics.mMesh[i].mNormals);
if (explode > 0.f) if (explode > 0.f)

View File

@@ -45,6 +45,7 @@
#include "pipeline.h" #include "pipeline.h"
#include "llviewerobjectlist.h" #include "llviewerobjectlist.h"
#include "llviewertexturelist.h" #include "llviewertexturelist.h"
#include "lltexturefetch.h"
#include "sgmemstat.h" #include "sgmemstat.h"
const S32 LL_SCROLL_BORDER = 1; const S32 LL_SCROLL_BORDER = 1;
@@ -151,10 +152,36 @@ void LLFloaterStats::buildStats()
stat_barp->mLabelSpacing = 500.f; stat_barp->mLabelSpacing = 500.f;
stat_barp->mPerSec = TRUE; 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 // Texture statistics
LLStatView *texture_statviewp = render_statviewp->addStatView("texture stat view", "Texture", "OpenDebugStatTexture", rect); 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 = texture_statviewp->addStat("Count", &(LLViewerStats::getInstance()->mNumImagesStat), "DebugStatModeTextureCount");
stat_barp->setUnitLabel(""); stat_barp->setUnitLabel("");
stat_barp->mMinBar = 0.f; stat_barp->mMinBar = 0.f;
@@ -365,6 +392,15 @@ void LLFloaterStats::buildStats()
stat_barp->mPerSec = FALSE; stat_barp->mPerSec = FALSE;
stat_barp->mDisplayMean = 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 = sim_statviewp->addStat("Script Events", &(LLViewerStats::getInstance()->mSimScriptEPS), "DebugStatModeSimScriptEvents");
stat_barp->setUnitLabel(" eps"); stat_barp->setUnitLabel(" eps");
stat_barp->mPrecision = 0; stat_barp->mPrecision = 0;
@@ -375,6 +411,35 @@ void LLFloaterStats::buildStats()
stat_barp->mPerSec = FALSE; stat_barp->mPerSec = FALSE;
stat_barp->mDisplayMean = 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 = sim_statviewp->addStat("Packets In", &(LLViewerStats::getInstance()->mSimInPPS), "DebugStatModeSimInPPS");
stat_barp->setUnitLabel(" pps"); stat_barp->setUnitLabel(" pps");
stat_barp->mPrecision = 0; stat_barp->mPrecision = 0;

View File

@@ -103,27 +103,6 @@ LLFloaterURLEntry::LLFloaterURLEntry(LLHandle<LLPanel> parent)
mPanelLandMediaHandle(parent) mPanelLandMediaHandle(parent)
{ {
LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml"); LLUICtrlFactory::getInstance()->buildFloater(this, "floater_url_entry.xml");
mMediaURLEdit = getChild<LLComboBox>("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; sInstance = NULL;
} }
BOOL LLFloaterURLEntry::postBuild()
{
mMediaURLEdit = getChild<LLComboBox>("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() void LLFloaterURLEntry::buildURLHistory()
{ {
LLCtrlListInterface* url_list = childGetListInterface("media_entry"); LLCtrlListInterface* url_list = childGetListInterface("media_entry");
@@ -157,7 +158,7 @@ void LLFloaterURLEntry::buildURLHistory()
void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type) void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_type)
{ {
LLPanelLandMedia* panel_media = (LLPanelLandMedia*)mPanelLandMediaHandle.get(); LLPanelLandMedia* panel_media = dynamic_cast<LLPanelLandMedia*>(mPanelLandMediaHandle.get());
if (panel_media) if (panel_media)
{ {
// status is ignored for now -- error = "none/none" // status is ignored for now -- error = "none/none"
@@ -166,21 +167,18 @@ void LLFloaterURLEntry::headerFetchComplete(U32 status, const std::string& mime_
} }
// Decrement the cursor // Decrement the cursor
getWindow()->decBusyCount(); getWindow()->decBusyCount();
childSetVisible("loading_label", false); getChildView("loading_label")->setVisible( false);
close(); close();
} }
// static // static
LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent) LLHandle<LLFloater> LLFloaterURLEntry::show(LLHandle<LLPanel> parent)
{ {
if (sInstance) if (!sInstance)
{
sInstance->open();
}
else
{ {
sInstance = new LLFloaterURLEntry(parent); sInstance = new LLFloaterURLEntry(parent);
} }
sInstance->open();
sInstance->updateFromLandMediaPanel(); sInstance->updateFromLandMediaPanel();
return sInstance->getHandle(); return sInstance->getHandle();
} }
@@ -239,7 +237,8 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
} }
// Discover the MIME type only for "http" scheme. // 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, LLHTTPClient::getHeaderOnly( media_url,
new LLMediaTypeResponder(self->getHandle())); new LLMediaTypeResponder(self->getHandle()));
@@ -250,13 +249,13 @@ void LLFloaterURLEntry::onBtnOK( void* userdata )
} }
// Grey the buttons until we get the header response // Grey the buttons until we get the header response
self->childSetEnabled("ok_btn", false); self->getChildView("ok_btn")->setEnabled(false);
self->childSetEnabled("cancel_btn", false); self->getChildView("cancel_btn")->setEnabled(false);
self->childSetEnabled("media_entry", false); self->getChildView("media_entry")->setEnabled(false);
// show progress bar here? // show progress bar here?
getWindow()->incBusyCount(); getWindow()->incBusyCount();
self->childSetVisible("loading_label", true); self->getChildView("loading_label")->setVisible( true);
} }
// static // static
@@ -298,7 +297,7 @@ bool LLFloaterURLEntry::callback_clear_url_list(const LLSD& notification, const
LLURLHistory::clear("parcel"); LLURLHistory::clear("parcel");
// cleared the list so disable Clear button // cleared the list so disable Clear button
childSetEnabled( "clear_btn", false ); getChildView("clear_btn")->setEnabled(false );
} }
return false; return false;
} }

View File

@@ -45,7 +45,7 @@ public:
// Can only be shown by LLPanelLandMedia, and pushes data back into // Can only be shown by LLPanelLandMedia, and pushes data back into
// that panel via the handle. // that panel via the handle.
static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle); static LLHandle<LLFloater> show(LLHandle<LLPanel> panel_land_media_handle);
/*virtual*/ BOOL postBuild();
void updateFromLandMediaPanel(); void updateFromLandMediaPanel();
void headerFetchComplete(U32 status, const std::string& mime_type); void headerFetchComplete(U32 status, const std::string& mime_type);

View File

@@ -104,6 +104,7 @@ void LLMemoryView::refreshProfile()
mLines.clear(); mLines.clear();
#if MEM_TRACK_MEM
if(mAlloc->isProfiling()) if(mAlloc->isProfiling())
{ {
const LLAllocatorHeapProfile &prof = mAlloc->getProfile(); const LLAllocatorHeapProfile &prof = mAlloc->getProfile();
@@ -118,6 +119,7 @@ void LLMemoryView::refreshProfile()
mLines.push_back(utf8string_to_wstring(ss.str())); mLines.push_back(utf8string_to_wstring(ss.str()));
} }
} }
#endif
} }
void LLMemoryView::draw() void LLMemoryView::draw()

View File

@@ -53,6 +53,7 @@
#include "llviewertexture.h" #include "llviewertexture.h"
#include "llviewerregion.h" #include "llviewerregion.h"
#include "llviewerstats.h" #include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
#include "llworld.h" #include "llworld.h"
#include "llstartup.h" #include "llstartup.h"
#include "llbuffer.h" #include "llbuffer.h"
@@ -61,6 +62,9 @@ class AIHTTPTimeoutPolicy;
extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout; extern AIHTTPTimeoutPolicy HTTPGetResponder_timeout;
extern AIHTTPTimeoutPolicy lcl_responder_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 class LLTextureFetchWorker : public LLWorkerClass
{ {
@@ -250,6 +254,8 @@ private:
S32 mDecodedDiscard; S32 mDecodedDiscard;
LLFrameTimer mRequestedTimer; LLFrameTimer mRequestedTimer;
LLFrameTimer mFetchTimer; LLFrameTimer mFetchTimer;
LLTimer mCacheReadTimer;
F32 mCacheReadTime;
LLTextureCache::handle_t mCacheReadHandle; LLTextureCache::handle_t mCacheReadHandle;
LLTextureCache::handle_t mCacheWriteHandle; LLTextureCache::handle_t mCacheWriteHandle;
std::vector<U8> mHttpBuffer; std::vector<U8> mHttpBuffer;
@@ -289,9 +295,6 @@ private:
S32 mLastPacket; S32 mLastPacket;
U16 mTotalPackets; U16 mTotalPackets;
U8 mImageCodec; U8 mImageCodec;
#if HTTP_METRICS
LLViewerAssetStats::duration_t mMetricsStartTime;
#endif
}; };
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -384,20 +387,6 @@ public:
} }
mFetcher->removeFromHTTPQueue(mID, data_size); 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 else
{ {
@@ -514,230 +503,6 @@ static bool sgConnectionThrottle() {
} }
#endif #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 //static
@@ -757,11 +522,6 @@ const char* LLTextureFetchWorker::sStateDescs[] = {
"DONE", "DONE",
}; };
#if HTTP_METRICS
// static
volatile bool LLTextureFetch::svMetricsDataBreak(true); // Start with a data break
#endif
// called from MAIN THREAD // called from MAIN THREAD
LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
@@ -786,6 +546,7 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mRequestedDiscard(-1), mRequestedDiscard(-1),
mLoadedDiscard(-1), mLoadedDiscard(-1),
mDecodedDiscard(-1), mDecodedDiscard(-1),
mCacheReadTime(0.f),
mCacheReadHandle(LLTextureCache::nullHandle()), mCacheReadHandle(LLTextureCache::nullHandle()),
mCacheWriteHandle(LLTextureCache::nullHandle()), mCacheWriteHandle(LLTextureCache::nullHandle()),
mRequestedSize(0), mRequestedSize(0),
@@ -810,9 +571,6 @@ LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher,
mLastPacket(-1), mLastPacket(-1),
mTotalPackets(0), mTotalPackets(0),
mImageCodec(IMG_CODEC_INVALID) mImageCodec(IMG_CODEC_INVALID)
#if HTTP_METRICS
,mMetricsStartTime(0)
#endif
{ {
mCanUseNET = mUrl.empty() ; mCanUseNET = mUrl.empty() ;
@@ -1064,6 +822,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority, mCacheReadHandle = mFetcher->mTextureCache->readFromCache(filename, mID, cache_priority,
offset, size, responder); offset, size, responder);
mCacheReadTimer.reset();
} }
else if (mUrl.empty()) else if (mUrl.empty())
{ {
@@ -1072,8 +831,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage);
mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority,
offset, size, responder); offset, size, responder);
mCacheReadTimer.reset();
} }
else if(mCanUseHTTP) else if(!mUrl.empty() && mCanUseHTTP)
{ {
if (!(mUrl.compare(0, 7, "http://") == 0)) if (!(mUrl.compare(0, 7, "http://") == 0))
{ {
@@ -1101,6 +861,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
} }
else else
{ {
//
//This should never happen
//
return false; return false;
} }
} }
@@ -1124,7 +887,7 @@ bool LLTextureFetchWorker::doWork(S32 param)
LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize() LL_DEBUGS("Texture") << mID << ": Cached. Bytes: " << mFormattedImage->getDataSize()
<< " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight()) << " Size: " << llformat("%dx%d",mFormattedImage->getWidth(),mFormattedImage->getHeight())
<< " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL; << " Desired Discard: " << mDesiredDiscard << " Desired Size: " << mDesiredSize << LL_ENDL;
// fall through LLTextureFetch::sCacheHitRate.addValue(100.f);
} }
else else
{ {
@@ -1139,7 +902,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL; LL_DEBUGS("Texture") << mID << ": Not in Cache" << LL_ENDL;
mState = LOAD_FROM_NETWORK; mState = LOAD_FROM_NETWORK;
} }
// fall through // fall through
LLTextureFetch::sCacheHitRate.addValue(0.f);
} }
} }
@@ -1198,15 +963,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
mRequestedDiscard = mDesiredDiscard; mRequestedDiscard = mDesiredDiscard;
mSentRequest = QUEUED; mSentRequest = QUEUED;
mFetcher->addToNetworkQueue(this); 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); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false; return false;
@@ -1217,12 +973,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
//llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end()); //llassert_always(mFetcher->mNetworkQueue.find(mID) != mFetcher->mNetworkQueue.end());
// Make certain this is in the network queue // Make certain this is in the network queue
//mFetcher->addToNetworkQueue(this); //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); //setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return false; return false;
} }
@@ -1247,33 +997,10 @@ bool LLTextureFetchWorker::doWork(S32 param)
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mState = DECODE_IMAGE; mState = DECODE_IMAGE;
mWriteToCacheState = SHOULD_WRITE; 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 else
{ {
mFetcher->addToNetworkQueue(this); // failsafe 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); setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
} }
return false; return false;
@@ -1340,15 +1067,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
mState = WAIT_HTTP_REQ; mState = WAIT_HTTP_REQ;
mFetcher->addToHTTPQueue(mID); 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) if(mRequestedOffset>0)
{ {
@@ -1573,11 +1291,12 @@ bool LLTextureFetchWorker::doWork(S32 param)
if (mState == DECODE_IMAGE) if (mState == DECODE_IMAGE)
{ {
static LLCachedControl<bool> textures_decode_disabled(gSavedSettings,"TextureDecodeDisabled"); static LLCachedControl<bool> 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 // for debug use, don't decode
mState = DONE; mState = DONE;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return true; return true;
} }
@@ -1585,7 +1304,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
{ {
// We aborted, don't decode // We aborted, don't decode
mState = DONE; mState = DONE;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return true; return true;
} }
@@ -1595,7 +1313,6 @@ bool LLTextureFetchWorker::doWork(S32 param)
//abort, don't decode //abort, don't decode
mState = DONE; mState = DONE;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return true; return true;
} }
if (mLoadedDiscard < 0) if (mLoadedDiscard < 0)
@@ -1604,10 +1321,9 @@ bool LLTextureFetchWorker::doWork(S32 param)
//abort, don't decode //abort, don't decode
mState = DONE; mState = DONE;
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority);
return true; return true;
} }
setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it
mRawImage = NULL; mRawImage = NULL;
mAuxImage = NULL; mAuxImage = NULL;
llassert_always(mFormattedImage.notNull()); 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; LL_DEBUGS("Texture") << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << LL_ENDL;
if (data_size > 0) if (data_size > 0)
{ {
LLViewerStatsRecorder::instance().textureFetch(data_size);
// *TODO: set the formatted image data here directly to avoid the copy // *TODO: set the formatted image data here directly to avoid the copy
llassert(mHttpBuffer.empty()); llassert(mHttpBuffer.empty());
mHttpBuffer.resize(data_size); mHttpBuffer.resize(data_size);
@@ -1932,6 +1649,7 @@ S32 LLTextureFetchWorker::callbackHttpGet(const LLChannelDescriptors& channels,
mLoaded = TRUE; mLoaded = TRUE;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
LLViewerStatsRecorder::instance().log(0.2f);
return data_size ; return data_size ;
} }
@@ -2017,6 +1735,7 @@ void LLTextureFetchWorker::callbackDecoded(bool success, LLImageRaw* raw, LLImag
mDecoded = TRUE; mDecoded = TRUE;
// llinfos << mID << " : DECODE COMPLETE " << llendl; // llinfos << mID << " : DECODE COMPLETE " << llendl;
setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority);
mCacheReadTime = mCacheReadTimer.getElapsedTimeF32();
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -2058,13 +1777,7 @@ LLTextureFetch::LLTextureFetch(LLTextureCache* cache, LLImageDecodeThread* image
mTextureBandwidth(0), mTextureBandwidth(0),
mHTTPTextureBits(0), mHTTPTextureBits(0),
mTotalHTTPRequests(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")); mTextureInfo.setUpLogging(gSavedSettings.getBOOL("LogTextureDownloadsToViewerLog"), gSavedSettings.getBOOL("LogTextureDownloadsToSimulator"), gSavedSettings.getU32("TextureLoggingThreshold"));
} }
@@ -2072,14 +1785,6 @@ LLTextureFetch::~LLTextureFetch()
{ {
clearDeleteList() ; clearDeleteList() ;
#if HTTP_METRICS
while (! mCommands.empty())
{
TFRequest * req(mCommands.front());
mCommands.erase(mCommands.begin());
delete req;
}
#endif
// ~LLQueuedThread() called here // ~LLQueuedThread() called here
} }
@@ -2341,6 +2046,11 @@ bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level,
discard_level = worker->mDecodedDiscard; discard_level = worker->mDecodedDiscard;
raw = worker->mRawImage; raw = worker->mRawImage;
aux = worker->mAuxImage; aux = worker->mAuxImage;
F32 cache_read_time = worker->mCacheReadTime;
if (cache_read_time != 0.f)
{
sCacheReadLatency.addValue(cache_read_time * 1000.f);
}
res = true; res = true;
LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL; LL_DEBUGS("Texture") << id << ": Request Finished. State: " << worker->mState << " Discard: " << discard_level << LL_ENDL;
worker->unlockWorkMutex(); worker->unlockWorkMutex();
@@ -2393,10 +2103,6 @@ S32 LLTextureFetch::getPending()
LLMutexLock lock(&mQueueMutex); LLMutexLock lock(&mQueueMutex);
res = mRequestQueue.size(); res = mRequestQueue.size();
#if HTTP_METRICS
res += mCurlPOSTRequestCount;
res += mCommands.size();
#endif
} }
unlockData(); unlockData();
return res; return res;
@@ -2414,22 +2120,7 @@ bool LLTextureFetch::runCondition()
// //
// Changes here may need to be reflected in getPending(). // Changes here may need to be reflected in getPending().
#if HTTP_METRICS return ! (mRequestQueue.empty() && mIdleThread); // From base class
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
} }
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
@@ -2437,10 +2128,6 @@ bool LLTextureFetch::runCondition()
// MAIN THREAD (unthreaded envs), WORKER THREAD (threaded envs) // MAIN THREAD (unthreaded envs), WORKER THREAD (threaded envs)
void LLTextureFetch::commonUpdate() 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() ; mNetworkQueueMutex.unlock() ;
return false; return false;
} }
LLViewerStatsRecorder::instance().textureFetch(data_size);
LLViewerStatsRecorder::instance().log(0.1f);
worker->lockWorkMutex(); worker->lockWorkMutex();
// Copy header data into image object
worker->mImageCodec = codec; // Copy header data into image object
worker->mTotalPackets = packets; worker->mImageCodec = codec;
worker->mTotalPackets = packets;
worker->mFileSize = (S32)totalbytes; worker->mFileSize = (S32)totalbytes;
llassert_always(totalbytes > 0); llassert_always(totalbytes > 0);
llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize);
@@ -2845,8 +2537,12 @@ bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U1
return false; return false;
} }
LLViewerStatsRecorder::instance().textureFetch(data_size);
LLViewerStatsRecorder::instance().log(0.1f);
worker->lockWorkMutex(); worker->lockWorkMutex();
res = worker->insertPacket(packet_num, data, data_size); res = worker->insertPacket(packet_num, data, data_size);
if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) || if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) ||
@@ -2959,277 +2655,12 @@ void LLTextureFetch::dump()
<< " STATE: " << worker->sStateDescs[worker->mState] << " STATE: " << worker->sStateDescs[worker->mState]
<< llendl; << llendl;
} }
}
////////////////////////////////////////////////////////////////////////////// llinfos << "LLTextureFetch ACTIVE_HTTP:" << llendl;
for (queue_t::const_iterator iter(mHTTPTextureQueue.begin());
// cross-thread command methods mHTTPTextureQueue.end() != iter;
++iter)
#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())
{ {
ret = mCommands.front(); llinfos << " ID: " << (*iter) << llendl;
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;
} }
} }
//////////////////////////////////////////////////////////////////////////////
// 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<LLSD::Real, int> 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

View File

@@ -46,9 +46,6 @@ class HTTPGetResponder;
class LLTextureCache; class LLTextureCache;
class LLImageDecodeThread; class LLImageDecodeThread;
class LLHost; class LLHost;
#if HTTP_METRICS
class LLViewerAssetStats;
#endif
// Interface class // Interface class
class LLTextureFetch : public LLWorkerThread class LLTextureFetch : public LLWorkerThread
@@ -98,22 +95,6 @@ public:
LLTextureInfo* getTextureInfo() { return &mTextureInfo; } 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: protected:
void addToNetworkQueue(LLTextureFetchWorker* worker); void addToNetworkQueue(LLTextureFetchWorker* worker);
void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel); void removeFromNetworkQueue(LLTextureFetchWorker* worker, bool cancel);
@@ -129,37 +110,6 @@ private:
/*virtual*/ void threadedUpdate(void); /*virtual*/ void threadedUpdate(void);
void commonUpdate(); 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: public:
LLUUID mDebugID; LLUUID mDebugID;
@@ -172,6 +122,11 @@ private:
LLMutex mQueueMutex; //to protect mRequestMap only LLMutex mQueueMutex; //to protect mRequestMap only
LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue. LLMutex mNetworkQueueMutex; //to protect mNetworkQueue, mHTTPTextureQueue and mCancelQueue.
public:
static LLStat sCacheHitRate;
static LLStat sCacheReadLatency;
private:
LLTextureCache* mTextureCache; LLTextureCache* mTextureCache;
LLImageDecodeThread* mImageDecodeThread; LLImageDecodeThread* mImageDecodeThread;
@@ -193,30 +148,6 @@ private:
//debug use //debug use
U32 mTotalHTTPRequests ; 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<TFRequest *> 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<S32> 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 #endif // LL_LLTEXTUREFETCH_H

View File

@@ -5179,6 +5179,18 @@ void process_sim_stats(LLMessageSystem *msg, void **user_data)
case LL_SIM_STAT_IOPUMPTIME: case LL_SIM_STAT_IOPUMPTIME:
LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value); LLViewerStats::getInstance()->mSimPumpIOMsec.addValue(stat_value);
break; 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: default:
// Used to be a commented out warning. // Used to be a commented out warning.
LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL; LL_DEBUGS("Messaging") << "Unknown stat id" << stat_id << LL_ENDL;
@@ -5799,6 +5811,35 @@ static std::string reason_from_transaction_type(S32 transaction_type,
} }
} }
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;
LLSD msg_args;
msg_args["MESSAGE"] = LLTrans::getString(message,args);
LLNotificationsUtil::add(notification,msg_args,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 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) static void process_money_balance_reply_extended(LLMessageSystem* msg)
{ {
// Added in server 1.40 and viewer 2.1, support for localization // Added in server 1.40 and viewer 2.1, support for localization
@@ -5831,26 +5872,6 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
return; 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 = std::string reason =
reason_from_transaction_type(transaction_type, item_description); reason_from_transaction_type(transaction_type, item_description);
@@ -5865,60 +5886,55 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
std::string message; std::string message;
static LLCachedControl<bool> no_transaction_clutter("LiruNoTransactionClutter", false); static LLCachedControl<bool> no_transaction_clutter("LiruNoTransactionClutter", false);
std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage"; std::string notification = no_transaction_clutter ? "Payment" : "SystemMessage";
LLSD final_args;
LLSD payload; LLSD payload;
bool you_paid_someone = (source_id == gAgentID); bool you_paid_someone = (source_id == gAgentID);
if (you_paid_someone) if (you_paid_someone)
{ {
args["NAME"] = dest_slurl;
is_name_group = is_dest_group; is_name_group = is_dest_group;
name_id = dest_id; name_id = dest_id;
if (!reason.empty()) if (!reason.empty())
{ {
if (dest_id.notNull()) if (dest_id.notNull())
{ {
message = success ? LLTrans::getString("you_paid_ldollars", args) : message = success ? "you_paid_ldollars" :
LLTrans::getString("you_paid_failure_ldollars", args); "you_paid_failure_ldollars";
} }
else else
{ {
// transaction fee to the system, eg, to create a group // transaction fee to the system, eg, to create a group
message = success ? LLTrans::getString("you_paid_ldollars_no_name", args) : message = success ? "you_paid_ldollars_no_name" :
LLTrans::getString("you_paid_failure_ldollars_no_name", args); "you_paid_failure_ldollars_no_name";
} }
} }
else else
{ {
if (dest_id.notNull()) if (dest_id.notNull())
{ {
message = success ? LLTrans::getString("you_paid_ldollars_no_reason", args) : message = success ? "you_paid_ldollars_no_reason" :
LLTrans::getString("you_paid_failure_ldollars_no_reason", args); "you_paid_failure_ldollars_no_reason";
} }
else else
{ {
// no target, no reason, you just paid money // no target, no reason, you just paid money
message = success ? LLTrans::getString("you_paid_ldollars_no_info", args) : message = success ? "you_paid_ldollars_no_info" :
LLTrans::getString("you_paid_failure_ldollars_no_info", args); "you_paid_failure_ldollars_no_info";
} }
} }
final_args["MESSAGE"] = message;
} }
else else
{ {
// ...someone paid you // ...someone paid you
args["NAME"] = source_slurl;
is_name_group = is_source_group; is_name_group = is_source_group;
name_id = source_id; name_id = source_id;
if (!reason.empty()) if (!reason.empty())
{ {
message = LLTrans::getString("paid_you_ldollars", args); message = "paid_you_ldollars";
} }
else else
{ {
message = LLTrans::getString("paid_you_ldollars_no_reason", args); message = "paid_you_ldollars_no_reason";
} }
final_args["MESSAGE"] = message;
// make notification loggable // make notification loggable
payload["from_id"] = source_id; payload["from_id"] = source_id;
@@ -5930,14 +5946,15 @@ static void process_money_balance_reply_extended(LLMessageSystem* msg)
if (is_name_group) if (is_name_group)
{ {
gCacheName->getGroup(name_id, gCacheName->getGroup(name_id,
boost::bind(&LLNotificationsUtil::add, boost::bind(&money_balance_group_notify,
notification, final_args, payload)); _1, _2, _3, message,
notification, args, payload));
} }
else else {
{
LLAvatarNameCache::get(name_id, LLAvatarNameCache::get(name_id,
boost::bind(&LLNotificationsUtil::add, boost::bind(&money_balance_avatar_notify,
notification, final_args, payload)); _1, _2, message,
notification, args, payload));
} }
} }

View File

@@ -66,6 +66,7 @@
#include "llsdutil.h" #include "llsdutil.h"
#include "llviewerregion.h" #include "llviewerregion.h"
#include "llviewerstats.h" #include "llviewerstats.h"
#include "llviewerstatsrecorder.h"
#include "llvovolume.h" #include "llvovolume.h"
#include "llvoavatarself.h" #include "llvoavatarself.h"
#include "lltoolmgr.h" #include "lltoolmgr.h"
@@ -113,6 +114,7 @@ extern LLPipeline gPipeline;
U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check. U32 LLViewerObjectList::sSimulatorMachineIndex = 1; // Not zero deliberately, to speed up index check.
std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex; std::map<U64, U32> LLViewerObjectList::sIPAndPortToIndex;
std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID; std::map<U64, LLUUID> LLViewerObjectList::sIndexAndLocalIDToUUID;
LLStat LLViewerObjectList::sCacheHitRate("object_cache_hits", 128);
LLViewerObjectList::LLViewerObjectList() LLViewerObjectList::LLViewerObjectList()
{ {
@@ -384,11 +386,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compressed_dpbuffer[2048]; U8 compressed_dpbuffer[2048];
LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048); LLDataPackerBinaryBuffer compressed_dp(compressed_dpbuffer, 2048);
LLDataPacker *cached_dpp = NULL; LLDataPacker *cached_dpp = NULL;
LLViewerStatsRecorder& recorder = LLViewerStatsRecorder::instance();
for (i = 0; i < num_objects; i++) for (i = 0; i < num_objects; i++)
{ {
// timer is unused?
LLTimer update_timer; LLTimer update_timer;
BOOL justCreated = FALSE; BOOL justCreated = FALSE;
S32 msg_size = 0;
if (cached) if (cached)
{ {
@@ -396,6 +401,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U32 crc; U32 crc;
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, id, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_CRC, crc, 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. // Lookup data packer and add this id to cache miss lists if necessary.
U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE; U8 cache_miss_type = LLViewerRegion::CACHE_MISS_TYPE_NONE;
@@ -411,9 +417,7 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
else else
{ {
// Cache Miss. // Cache Miss.
#if LL_RECORD_VIEWER_STATS recorder.cacheMissEvent(id, update_type, cache_miss_type, msg_size);
LLViewerStatsRecorder::instance()->recordCacheMissEvent(id, update_type, cache_miss_type);
#endif
continue; // no data packer, skip this object 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); mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, compressed_dpbuffer, 0, i);
compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length); compressed_dp.assignBuffer(compressed_dpbuffer, uncompressed_length);
if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
if (update_type != OUT_TERSE_IMPROVED)
{ {
compressed_dp.unpackUUID(fullid, "ID"); compressed_dp.unpackUUID(fullid, "ID");
compressed_dp.unpackU32(local_id, "LocalID"); 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); mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, i);
msg_size += sizeof(U32);
getUUIDFromLocal(fullid, getUUIDFromLocal(fullid,
local_id, local_id,
gMessageSystem->getSenderIP(), gMessageSystem->getSenderIP(),
@@ -467,10 +472,12 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
mNumUnknownUpdates++; mNumUnknownUpdates++;
} }
} }
else else // OUT_FULL only?
{ {
mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i); mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_FullID, fullid, i);
mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_ID, local_id, 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; // llinfos << "Full Update, obj " << local_id << ", global ID" << fullid << "from " << mesgsys->getSender() << llendl;
} }
objectp = findObject(fullid); objectp = findObject(fullid);
@@ -515,28 +522,33 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
{ {
if (update_type == OUT_TERSE_IMPROVED) 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; continue;
} }
} }
else if (cached) else if (cached) // Cache hit only?
{ {
} }
else else
{ {
if (update_type != OUT_FULL) 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; continue;
} }
mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i); mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_PCode, pcode, i);
msg_size += sizeof(U8);
} }
#ifdef IGNORE_DEAD #ifdef IGNORE_DEAD
if (mDeadObjects.find(fullid) != mDeadObjects.end()) if (mDeadObjects.find(fullid) != mDeadObjects.end())
{ {
mNumDeadObjectUpdates++; 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; continue;
} }
#endif #endif
@@ -553,10 +565,14 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender()); objectp = createObject(pcode, regionp, fullid, local_id, gMessageSystem->getSender());
if (!objectp) if (!objectp)
{ {
llinfos << "createObject failure for object: " << fullid << llendl;
recorder.objectUpdateFailure(local_id, update_type, msg_size);
continue; continue;
} }
justCreated = TRUE; justCreated = TRUE;
mNumNewObjects++; mNumNewObjects++;
sCacheHitRate.addValue(cached ? 100.f : 0.f);
} }
@@ -568,15 +584,16 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
bool bCached = false; bool bCached = false;
if (compressed) if (compressed)
{ {
if (update_type != OUT_TERSE_IMPROVED) if (update_type != OUT_TERSE_IMPROVED) // OUT_FULL_COMPRESSED only?
{ {
objectp->mLocalID = local_id; objectp->mLocalID = local_id;
} }
processUpdateCore(objectp, user_data, i, update_type, &compressed_dp, justCreated); 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; 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) else if (cached)
@@ -592,11 +609,13 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
} }
processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated); processUpdateCore(objectp, user_data, i, update_type, NULL, justCreated);
} }
recorder.objectUpdateEvent(local_id, update_type, objectp, msg_size);
objectp->setLastUpdateType(update_type); objectp->setLastUpdateType(update_type);
objectp->setLastUpdateCached(bCached); objectp->setLastUpdateCached(bCached);
} }
recorder.log(0.2f);
LLVOAvatar::cullAvatarsByPixelArea(); LLVOAvatar::cullAvatarsByPixelArea();
} }

View File

@@ -205,6 +205,8 @@ public:
std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects std::vector<OrphanInfo> mOrphanChildren; // UUID's of orphaned objects
S32 mNumOrphans; S32 mNumOrphans;
static LLStat sCacheHitRate;
typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t; typedef std::vector<LLPointer<LLViewerObject> > vobj_list_t;
vobj_list_t mObjects; vobj_list_t mObjects;

View File

@@ -1405,11 +1405,8 @@ void LLViewerRegion::requestCacheMisses()
mCacheDirty = TRUE ; mCacheDirty = TRUE ;
// llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl; // llinfos << "KILLDEBUG Sent cache miss full " << full_count << " crc " << crc_count << llendl;
#if LL_RECORD_VIEWER_STATS LLViewerStatsRecorder::instance().requestCacheMissesEvent(full_count + crc_count);
LLViewerStatsRecorder::instance()->beginObjectUpdateEvents(this); LLViewerStatsRecorder::instance().log(0.2f);
LLViewerStatsRecorder::instance()->recordRequestCacheMissesEvent(full_count + crc_count);
LLViewerStatsRecorder::instance()->endObjectUpdateEvents();
#endif
} }
void LLViewerRegion::dumpCache() void LLViewerRegion::dumpCache()

View File

@@ -1887,18 +1887,19 @@ BOOL LLViewerShaderMgr::loadShadersObject()
if (success) if (success)
{ {
gObjectPreviewProgram.mName = "Simple Shader"; gObjectPreviewProgram.mName = "Simple Shader";
gObjectPreviewProgram.mFeatures.calculatesLighting = true; gObjectPreviewProgram.mFeatures.calculatesLighting = false;
gObjectPreviewProgram.mFeatures.calculatesAtmospherics = true; gObjectPreviewProgram.mFeatures.calculatesAtmospherics = false;
gObjectPreviewProgram.mFeatures.hasGamma = true; gObjectPreviewProgram.mFeatures.hasGamma = false;
gObjectPreviewProgram.mFeatures.hasAtmospherics = true; gObjectPreviewProgram.mFeatures.hasAtmospherics = false;
gObjectPreviewProgram.mFeatures.hasLighting = true; gObjectPreviewProgram.mFeatures.hasLighting = false;
gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0; gObjectPreviewProgram.mFeatures.mIndexedTextureChannels = 0;
gObjectPreviewProgram.mFeatures.disableTextureIndex = true; gObjectPreviewProgram.mFeatures.disableTextureIndex = true;
gObjectPreviewProgram.mShaderFiles.clear(); gObjectPreviewProgram.mShaderFiles.clear();
gObjectPreviewProgram.mShaderFiles.push_back(make_pair("objects/previewV.glsl", GL_VERTEX_SHADER_ARB)); 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]; gObjectPreviewProgram.mShaderLevel = mVertexShaderLevel[SHADER_OBJECT];
success = gObjectPreviewProgram.createShader(NULL, NULL); success = gObjectPreviewProgram.createShader(NULL, NULL);
gObjectPreviewProgram.mFeatures.hasLighting = true;
} }
if (success) if (success)

View File

@@ -239,6 +239,9 @@ LLViewerStats::LLViewerStats() :
mSimSimPhysicsStepMsec("simsimphysicsstepmsec"), mSimSimPhysicsStepMsec("simsimphysicsstepmsec"),
mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"), mSimSimPhysicsShapeUpdateMsec("simsimphysicsshapeupdatemsec"),
mSimSimPhysicsOtherMsec("simsimphysicsothermsec"), mSimSimPhysicsOtherMsec("simsimphysicsothermsec"),
mSimSimAIStepMsec("simsimaistepmsec"),
mSimSimSkippedSilhouetteSteps("simsimskippedsilhouettesteps"),
mSimSimPctSteppedCharacters("simsimpctsteppedcharacters"),
mSimAgentMsec("simagentmsec"), mSimAgentMsec("simagentmsec"),
mSimImagesMsec("simimagesmsec"), mSimImagesMsec("simimagesmsec"),
mSimScriptMsec("simscriptmsec"), mSimScriptMsec("simscriptmsec"),
@@ -250,6 +253,7 @@ LLViewerStats::LLViewerStats() :
mSimObjects("simobjects"), mSimObjects("simobjects"),
mSimActiveObjects("simactiveobjects"), mSimActiveObjects("simactiveobjects"),
mSimActiveScripts("simactivescripts"), mSimActiveScripts("simactivescripts"),
mSimPctScriptsRun("simpctscriptsrun"),
mSimInPPS("siminpps"), mSimInPPS("siminpps"),
mSimOutPPS("simoutpps"), mSimOutPPS("simoutpps"),
mSimPendingDownloads("simpendingdownloads"), mSimPendingDownloads("simpendingdownloads"),
@@ -292,19 +296,19 @@ LLViewerStats::~LLViewerStats()
void LLViewerStats::resetStats() void LLViewerStats::resetStats()
{ {
LLViewerStats::getInstance()->mKBitStat.reset(); LLViewerStats& stats = LLViewerStats::instance();
LLViewerStats::getInstance()->mLayersKBitStat.reset(); stats.mKBitStat.reset();
LLViewerStats::getInstance()->mObjectKBitStat.reset(); stats.mLayersKBitStat.reset();
LLViewerStats::getInstance()->mTextureKBitStat.reset(); stats.mObjectKBitStat.reset();
LLViewerStats::getInstance()->mVFSPendingOperations.reset(); stats.mTextureKBitStat.reset();
LLViewerStats::getInstance()->mAssetKBitStat.reset(); stats.mVFSPendingOperations.reset();
LLViewerStats::getInstance()->mPacketsInStat.reset(); stats.mAssetKBitStat.reset();
LLViewerStats::getInstance()->mPacketsLostStat.reset(); stats.mPacketsInStat.reset();
LLViewerStats::getInstance()->mPacketsOutStat.reset(); stats.mPacketsLostStat.reset();
LLViewerStats::getInstance()->mFPSStat.reset(); stats.mPacketsOutStat.reset();
LLViewerStats::getInstance()->mTexturePacketsStat.reset(); stats.mFPSStat.reset();
stats.mTexturePacketsStat.reset();
LLViewerStats::getInstance()->mAgentPositionSnaps.reset(); stats.mAgentPositionSnaps.reset();
} }
@@ -329,55 +333,55 @@ void LLViewerStats::updateFrameStats(const F64 time_diff)
{ {
if (mPacketsLostPercentStat.getCurrent() > 5.0) 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) 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) 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) 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) 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) 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) if (gFrameCount && mLastTimeDiff > 0.0)
{ {
// new "stutter" meter // new "stutter" meter
setStat(LLViewerStats::ST_FPS_DROP_50_RATIO, setStat(ST_FPS_DROP_50_RATIO,
(getStat(LLViewerStats::ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) + (getStat(ST_FPS_DROP_50_RATIO) * (F64)(gFrameCount - 1) +
(time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount); (time_diff >= 2.0 * mLastTimeDiff ? 1.0 : 0.0)) / gFrameCount);
// old stats that were never really used // old stats that were never really used
setStat(LLViewerStats::ST_FRAMETIME_JITTER, setStat(ST_FRAMETIME_JITTER,
(getStat(LLViewerStats::ST_FRAMETIME_JITTER) * (gFrameCount - 1) + (getStat(ST_FRAMETIME_JITTER) * (gFrameCount - 1) +
fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount); fabs(mLastTimeDiff - time_diff) / mLastTimeDiff) / gFrameCount);
F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount; F32 average_frametime = gRenderStartTime.getElapsedTimeF32() / (F32)gFrameCount;
setStat(LLViewerStats::ST_FRAMETIME_SLEW, setStat(ST_FRAMETIME_SLEW,
(getStat(LLViewerStats::ST_FRAMETIME_SLEW) * (gFrameCount - 1) + (getStat(ST_FRAMETIME_SLEW) * (gFrameCount - 1) +
fabs(average_frametime - time_diff) / average_frametime) / gFrameCount); fabs(average_frametime - time_diff) / average_frametime) / gFrameCount);
F32 max_bandwidth = gViewerThrottle.getMaxBandwidth(); F32 max_bandwidth = gViewerThrottle.getMaxBandwidth();
F32 delta_bandwidth = gViewerThrottle.getCurrentBandwidth() - max_bandwidth; 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 gTotalWorldBytes = 0, gTotalObjectBytes = 0, gTotalTextureBytes = 0, gSimPingCount = 0;
U32 gObjectBits = 0; U32 gObjectBits = 0;
F32 gAvgSimPing = 0.f; 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 gVisCompared;
extern U32 gVisTested; extern U32 gVisTested;
std::map<S32,LLFrameTimer> gDebugTimers; LLFrameTimer gTextureTimer;
std::map<S32,std::string> gDebugTimerLabel;
void init_statistics() void update_statistics()
{
// Label debug timers
gDebugTimerLabel[0] = "Texture";
}
void update_statistics(U32 frame_count)
{ {
gTotalWorldBytes += gVLManager.getTotalBytes(); gTotalWorldBytes += gVLManager.getTotalBytes();
gTotalObjectBytes += gObjectBits / 8; gTotalObjectBytes += gObjectBits / 8;
LLViewerStats& stats = LLViewerStats::instance();
// make sure we have a valid time delta for this frame // make sure we have a valid time delta for this frame
if (gFrameIntervalSeconds > 0.f) if (gFrameIntervalSeconds > 0.f)
{ {
@@ -606,51 +605,51 @@ void update_statistics(U32 frame_count)
LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_TOOLBOX_SECONDS, gFrameIntervalSeconds);
} }
} }
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable")); stats.setStat(LLViewerStats::ST_ENABLE_VBO, (F64)gSavedSettings.getBOOL("RenderVBOEnable"));
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail()); stats.setStat(LLViewerStats::ST_LIGHTING_DETAIL, (F64)gPipeline.getLightingDetail());
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip")); stats.setStat(LLViewerStats::ST_DRAW_DIST, (F64)gSavedSettings.getF32("RenderFarClip"));
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles")); stats.setStat(LLViewerStats::ST_CHAT_BUBBLES, (F64)gSavedSettings.getBOOL("UseChatBubbles"));
#if 0 // 1.9.2 #if 0 // 1.9.2
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_OBJECTS, (F64)gSavedSettings.getS32("VertexShaderLevelObject")); 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_AVATAR, (F64)gSavedSettings.getBOOL("VertexShaderLevelAvatar"));
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment")); LLViewerStats::getInstance()->setStat(LLViewerStats::ST_SHADER_ENVIRONMENT, (F64)gSavedSettings.getBOOL("VertexShaderLevelEnvironment"));
#endif #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 idle_secs = gDebugView->mFastTimerView->getTime("Idle");
F64 network_secs = gDebugView->mFastTimerView->getTime("Network"); F64 network_secs = gDebugView->mFastTimerView->getTime("Network");
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs); stats.setStat(LLViewerStats::ST_UPDATE_SECS, idle_secs - network_secs);
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_NETWORK_SECS, network_secs); stats.setStat(LLViewerStats::ST_NETWORK_SECS, network_secs);
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images")); stats.setStat(LLViewerStats::ST_IMAGE_SECS, gDebugView->mFastTimerView->getTime("Update Images"));
LLViewerStats::getInstance()->setStat(LLViewerStats::ST_REBUILD_SECS, gDebugView->mFastTimerView->getTime("Sort Draw State")); stats.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_RENDER_SECS, gDebugView->mFastTimerView->getTime("Geometry"));
LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost()); LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(gAgent.getRegion()->getHost());
if (cdp) if (cdp)
{ {
LLViewerStats::getInstance()->mSimPingStat.addValue(cdp->getPingDelay()); stats.mSimPingStat.addValue(cdp->getPingDelay());
gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1); gAvgSimPing = ((gAvgSimPing * (F32)gSimPingCount) + (F32)(cdp->getPingDelay())) / ((F32)gSimPingCount + 1);
gSimPingCount++; gSimPingCount++;
} }
else 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()); F32 layer_bits = (F32)(gVLManager.getLandBits() + gVLManager.getWindBits() + gVLManager.getCloudBits());
LLViewerStats::getInstance()->mLayersKBitStat.addValue(layer_bits/1024.f); stats.mLayersKBitStat.addValue(layer_bits/1024.f);
LLViewerStats::getInstance()->mObjectKBitStat.addValue(gObjectBits/1024.f); stats.mObjectKBitStat.addValue(gObjectBits/1024.f);
LLViewerStats::getInstance()->mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending()); stats.mVFSPendingOperations.addValue(LLVFile::getVFSThread()->getPending());
LLViewerStats::getInstance()->mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f); stats.mAssetKBitStat.addValue(gTransferManager.getTransferBitsIn(LLTCT_ASSET)/1024.f);
gTransferManager.resetTransferBitsIn(LLTCT_ASSET); gTransferManager.resetTransferBitsIn(LLTCT_ASSET);
if (LLAppViewer::getTextureFetch()->getNumRequests() == 0) if (LLAppViewer::getTextureFetch()->getNumRequests() == 0)
{ {
gDebugTimers[0].pause(); gTextureTimer.pause();
} }
else else
{ {
gDebugTimers[0].unpause(); gTextureTimer.unpause();
} }
{ {
@@ -662,7 +661,7 @@ void update_statistics(U32 frame_count)
visible_avatar_frames = 1.f; visible_avatar_frames = 1.f;
avg_visible_avatars = (avg_visible_avatars * (F32)(visible_avatar_frames - 1.f) + visible_avatars) / visible_avatar_frames; 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()->updateNetStats();
LLWorld::getInstance()->requestCacheMisses(); LLWorld::getInstance()->requestCacheMisses();
@@ -672,14 +671,14 @@ void update_statistics(U32 frame_count)
gObjectBits = 0; gObjectBits = 0;
// gDecodedBits = 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; static LLFrameTimer texture_stats_timer;
if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq) if (texture_stats_timer.getElapsedTimeF32() >= texture_stats_freq)
{ {
LLViewerStats::getInstance()->mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f); stats.mTextureKBitStat.addValue(LLViewerTextureList::sTextureBits/1024.f);
LLViewerStats::getInstance()->mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets); stats.mTexturePacketsStat.addValue(LLViewerTextureList::sTexturePackets);
LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerTextureList::sTextureBits/1024.f/texture_stats_timer.getElapsedTimeF32()); LLAppViewer::getTextureFetch()->setTextureBandwidth(LLViewerTextureList::sTextureBits/1024.f/texture_stats_timer.getElapsedTimeF32());
gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8; gTotalTextureBytes += LLViewerTextureList::sTextureBits / 8;
LLViewerTextureList::sTextureBits = 0; LLViewerTextureList::sTextureBits = 0;
@@ -693,7 +692,7 @@ void update_statistics(U32 frame_count)
static LLFrameTimer mem_stats_timer; static LLFrameTimer mem_stats_timer;
if (mem_stats_timer.getElapsedTimeF32() >= mem_stats_freq) 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(); mem_stats_timer.reset();
} }
} }
@@ -813,6 +812,7 @@ void send_stats()
system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass(); system["gpu_class"] = (S32)LLFeatureManager::getInstance()->getGPUClass();
system["gpu_vendor"] = gGLManager.mGLVendorShort; system["gpu_vendor"] = gGLManager.mGLVendorShort;
system["gpu_version"] = gGLManager.mDriverVersionVendorString; system["gpu_version"] = gGLManager.mDriverVersionVendorString;
system["opengl_version"] = gGLManager.mGLVersionString;
LLSD &download = body["downloads"]; LLSD &download = body["downloads"];
@@ -859,10 +859,7 @@ void send_stats()
S32 window_height = gViewerWindow->getWindowHeightRaw(); S32 window_height = gViewerWindow->getWindowHeightRaw();
S32 window_size = (window_width * window_height) / 1024; S32 window_size = (window_width * window_height) / 1024;
misc["string_1"] = llformat("%d", window_size); 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", gTextureTimer.getElapsedTimeF32(), gFrameTimeSeconds);
{
misc["string_2"] = llformat("Texture Time: %.2f, Total Time: %.2f", gDebugTimers[0].getElapsedTimeF32(), gFrameTimeSeconds);
}
// misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21 // misc["int_1"] = LLSD::Integer(gSavedSettings.getU32("RenderQualityPerformance")); // Steve: 1.21
// misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21 // misc["int_2"] = LLSD::Integer(gFrameStalls); // Steve: 1.21

View File

@@ -39,88 +39,91 @@
class LLViewerStats : public LLSingleton<LLViewerStats> class LLViewerStats : public LLSingleton<LLViewerStats>
{ {
public: public:
LLStat mKBitStat; LLStat mKBitStat,
LLStat mLayersKBitStat; mLayersKBitStat,
LLStat mObjectKBitStat; mObjectKBitStat,
LLStat mAssetKBitStat; mAssetKBitStat,
LLStat mTextureKBitStat; mTextureKBitStat,
LLStat mVFSPendingOperations; mVFSPendingOperations,
LLStat mObjectsDrawnStat; mObjectsDrawnStat,
LLStat mObjectsCulledStat; mObjectsCulledStat,
LLStat mObjectsTestedStat; mObjectsTestedStat,
LLStat mObjectsComparedStat; mObjectsComparedStat,
LLStat mObjectsOccludedStat; mObjectsOccludedStat,
LLStat mFPSStat; mFPSStat,
LLStat mPacketsInStat; mPacketsInStat,
LLStat mPacketsLostStat; mPacketsLostStat,
LLStat mPacketsOutStat; mPacketsOutStat,
LLStat mPacketsLostPercentStat; mPacketsLostPercentStat,
LLStat mTexturePacketsStat; mTexturePacketsStat,
LLStat mActualInKBitStat; // From the packet ring (when faking a bad connection) mActualInKBitStat, // From the packet ring (when faking a bad connection)
LLStat mActualOutKBitStat; // From the packet ring (when faking a bad connection) mActualOutKBitStat, // From the packet ring (when faking a bad connection)
LLStat mTrianglesDrawnStat; mTrianglesDrawnStat,
LLStat mMallocStat; mMallocStat;
// Simulator stats // Simulator stats
LLStat mSimTimeDilation; LLStat mSimTimeDilation,
LLStat mSimFPS; mSimFPS,
LLStat mSimPhysicsFPS; mSimPhysicsFPS,
LLStat mSimAgentUPS; mSimAgentUPS,
LLStat mSimScriptEPS; mSimScriptEPS,
LLStat mSimFrameMsec; mSimFrameMsec,
LLStat mSimNetMsec; mSimNetMsec,
LLStat mSimSimOtherMsec; mSimSimOtherMsec,
LLStat mSimSimPhysicsMsec; mSimSimPhysicsMsec,
LLStat mSimSimPhysicsStepMsec; mSimSimPhysicsStepMsec,
LLStat mSimSimPhysicsShapeUpdateMsec; mSimSimPhysicsShapeUpdateMsec,
LLStat mSimSimPhysicsOtherMsec; mSimSimPhysicsOtherMsec,
mSimSimAIStepMsec,
mSimSimSkippedSilhouetteSteps,
mSimSimPctSteppedCharacters,
LLStat mSimAgentMsec; mSimAgentMsec,
LLStat mSimImagesMsec; mSimImagesMsec,
LLStat mSimScriptMsec; mSimScriptMsec,
LLStat mSimSpareMsec; mSimSpareMsec,
LLStat mSimSleepMsec; mSimSleepMsec,
LLStat mSimPumpIOMsec; mSimPumpIOMsec,
LLStat mSimMainAgents; mSimMainAgents,
LLStat mSimChildAgents; mSimChildAgents,
LLStat mSimObjects; mSimObjects,
LLStat mSimActiveObjects; mSimActiveObjects,
LLStat mSimActiveScripts; mSimActiveScripts,
mSimPctScriptsRun,
LLStat mSimInPPS; mSimInPPS,
LLStat mSimOutPPS; mSimOutPPS,
LLStat mSimPendingDownloads; mSimPendingDownloads,
LLStat mSimPendingUploads; mSimPendingUploads,
LLStat mSimPendingLocalUploads; mSimPendingLocalUploads,
LLStat mSimTotalUnackedBytes; mSimTotalUnackedBytes,
LLStat mPhysicsPinnedTasks; mPhysicsPinnedTasks,
LLStat mPhysicsLODTasks; mPhysicsLODTasks,
LLStat mPhysicsMemoryAllocated; mPhysicsMemoryAllocated,
LLStat mSimPingStat; mSimPingStat,
LLStat mNumImagesStat; mNumImagesStat,
LLStat mNumRawImagesStat; mNumRawImagesStat,
LLStat mGLTexMemStat; mGLTexMemStat,
LLStat mGLBoundMemStat; mGLBoundMemStat,
LLStat mRawMemStat; mRawMemStat,
LLStat mFormattedMemStat; mFormattedMemStat,
LLStat mNumObjectsStat; mNumObjectsStat,
LLStat mNumActiveObjectsStat; mNumActiveObjectsStat,
LLStat mNumNewObjectsStat; mNumNewObjectsStat,
LLStat mNumSizeCulledStat; mNumSizeCulledStat,
LLStat mNumVisCulledStat; mNumVisCulledStat;
void resetStats(); void resetStats();
public: public:
// If you change this, please also add a corresponding text label // If you change this, please also add a corresponding text label in llviewerstats.cpp
// in statTypeToText in llviewerstats.cpp
enum EStatType enum EStatType
{ {
ST_VERSION = 0, ST_VERSION = 0,
@@ -251,7 +254,7 @@ public:
inline F32 getStdDev() const inline F32 getStdDev() const
{ {
const F32 mean = getMean(); 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 inline U32 getCount() const
@@ -291,14 +294,12 @@ private:
static const F32 SEND_STATS_PERIOD = 300.0f; static const F32 SEND_STATS_PERIOD = 300.0f;
// The following are from (older?) statistics code found in appviewer. // The following are from (older?) statistics code found in appviewer.
void init_statistics();
void reset_statistics(); void reset_statistics();
void output_statistics(void*); void output_statistics(void*);
void update_statistics(U32 frame_count); void update_statistics();
void send_stats(); void send_stats();
extern std::map<S32,LLFrameTimer> gDebugTimers; extern LLFrameTimer gTextureTimer;
extern std::map<S32,std::string> gDebugTimerLabel;
extern U32 gTotalTextureBytes; extern U32 gTotalTextureBytes;
extern U32 gTotalObjectBytes; extern U32 gTotalObjectBytes;
extern U32 gTotalTextureBytesPerBoostLevel[] ; extern U32 gTotalTextureBytesPerBoostLevel[] ;

View File

@@ -27,7 +27,6 @@
#include "llviewerprecompiledheaders.h" #include "llviewerprecompiledheaders.h"
#include "llviewerstatsrecorder.h" #include "llviewerstatsrecorder.h"
#if LL_RECORD_VIEWER_STATS
#include "llfile.h" #include "llfile.h"
#include "llviewerregion.h" #include "llviewerregion.h"
@@ -45,9 +44,8 @@ LLViewerStatsRecorder* LLViewerStatsRecorder::sInstance = NULL;
LLViewerStatsRecorder::LLViewerStatsRecorder() : LLViewerStatsRecorder::LLViewerStatsRecorder() :
mObjectCacheFile(NULL), mObjectCacheFile(NULL),
mTimer(), mTimer(),
mRegionp(NULL), mStartTime(0.0),
mStartTime(0.f), mLastSnapshotTime(0.0)
mProcessingTime(0.f)
{ {
if (NULL != sInstance) if (NULL != sInstance)
{ {
@@ -61,112 +59,77 @@ LLViewerStatsRecorder::~LLViewerStatsRecorder()
{ {
if (mObjectCacheFile != NULL) if (mObjectCacheFile != NULL)
{ {
// last chance snapshot
writeToLog(0.f);
LLFile::close(mObjectCacheFile); LLFile::close(mObjectCacheFile);
mObjectCacheFile = NULL; 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() void LLViewerStatsRecorder::clearStats()
{ {
mObjectCacheHitCount = 0; mObjectCacheHitCount = 0;
mObjectCacheHitSize = 0;
mObjectCacheMissFullCount = 0; mObjectCacheMissFullCount = 0;
mObjectCacheMissFullSize = 0;
mObjectCacheMissCrcCount = 0; mObjectCacheMissCrcCount = 0;
mObjectCacheMissCrcSize = 0;
mObjectFullUpdates = 0; mObjectFullUpdates = 0;
mObjectFullUpdatesSize = 0;
mObjectTerseUpdates = 0; mObjectTerseUpdates = 0;
mObjectTerseUpdatesSize = 0;
mObjectCacheMissRequests = 0; mObjectCacheMissRequests = 0;
mObjectCacheMissResponses = 0; mObjectCacheMissResponses = 0;
mObjectCacheMissResponsesSize = 0;
mObjectCacheUpdateDupes = 0; mObjectCacheUpdateDupes = 0;
mObjectCacheUpdateChanges = 0; mObjectCacheUpdateChanges = 0;
mObjectCacheUpdateAdds = 0; mObjectCacheUpdateAdds = 0;
mObjectCacheUpdateReplacements = 0; mObjectCacheUpdateReplacements = 0;
mObjectUpdateFailures = 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++; 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) if (LLViewerRegion::CACHE_MISS_TYPE_FULL == cache_miss_type)
{ {
mObjectCacheMissFullCount++; mObjectCacheMissFullCount++;
mObjectCacheMissFullSize += msg_size;
} }
else else
{ {
mObjectCacheMissCrcCount++; 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) switch (update_type)
{ {
case OUT_FULL: case OUT_FULL:
mObjectFullUpdates++; mObjectFullUpdates++;
mObjectFullUpdatesSize += msg_size;
break; break;
case OUT_TERSE_IMPROVED: case OUT_TERSE_IMPROVED:
mObjectTerseUpdates++; mObjectTerseUpdates++;
mObjectTerseUpdatesSize += msg_size;
break; break;
case OUT_FULL_COMPRESSED: case OUT_FULL_COMPRESSED:
mObjectCacheMissResponses++; mObjectCacheMissResponses++;
mObjectCacheMissResponsesSize += msg_size;
break; break;
case OUT_FULL_CACHED: case OUT_FULL_CACHED:
mObjectCacheHitCount++; mObjectCacheHitCount++;
mObjectCacheHitSize += msg_size;
break; break;
default: default:
llwarns << "Unknown update_type" << llendl; 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) switch (update_result)
{ {
@@ -201,9 +164,15 @@ void LLViewerStatsRecorder::recordRequestCacheMissesEvent(S32 count)
mObjectCacheMissRequests += 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, " << mObjectCacheHitCount << " hits, "
<< mObjectCacheMissFullCount << " full misses, " << mObjectCacheMissFullCount << " full misses, "
<< mObjectCacheMissCrcCount << " crc misses, " << mObjectCacheMissCrcCount << " crc misses, "
@@ -218,41 +187,81 @@ void LLViewerStatsRecorder::endObjectUpdateEvents()
<< mObjectUpdateFailures << " update failures" << mObjectUpdateFailures << " update failures"
<< llendl; << llendl;
S32 total_objects = mObjectCacheHitCount + mObjectCacheMissCrcCount + mObjectCacheMissFullCount + mObjectFullUpdates + mObjectTerseUpdates + mObjectCacheMissRequests + mObjectCacheMissResponses + mObjectCacheUpdateDupes + mObjectCacheUpdateChanges + mObjectCacheUpdateAdds + mObjectCacheUpdateReplacements + mObjectUpdateFailures; if (mObjectCacheFile == NULL)
if (mObjectCacheFile != NULL &&
total_objects > 0)
{ {
std::ostringstream data_msg; mStartTime = LLTimer::getTotalSeconds();
F32 processing32 = (F32) ((LLTimer::getTotalTime() - mProcessingTime) / 1000.0); 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() fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
<< ", " << processing32 }
<< ", " << mObjectCacheHitCount else
<< ", " << mObjectCacheMissFullCount {
<< ", " << mObjectCacheMissCrcCount llwarns << "Couldn't open " << STATS_FILE_NAME << " for logging." << llendl;
<< ", " << mObjectFullUpdates return;
<< ", " << mObjectTerseUpdates }
<< ", " << mObjectCacheMissRequests
<< ", " << mObjectCacheMissResponses
<< ", " << mObjectCacheUpdateDupes
<< ", " << mObjectCacheUpdateChanges
<< ", " << mObjectCacheUpdateAdds
<< ", " << mObjectCacheUpdateReplacements
<< ", " << mObjectUpdateFailures
<< "\n";
fwrite(data_msg.str().c_str(), 1, data_msg.str().size(), mObjectCacheFile );
} }
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(); clearStats();
} }
F32 LLViewerStatsRecorder::getTimeSinceStart() 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;
}

View File

@@ -35,63 +35,111 @@
#define LL_RECORD_VIEWER_STATS 0 #define LL_RECORD_VIEWER_STATS 0
#if LL_RECORD_VIEWER_STATS
#include "llframetimer.h" #include "llframetimer.h"
#include "llviewerobject.h" #include "llviewerobject.h"
#include "llviewerregion.h" #include "llviewerregion.h"
class LLMutex; class LLMutex;
class LLViewerRegion;
class LLViewerObject; class LLViewerObject;
class LLViewerStatsRecorder class LLViewerStatsRecorder : public LLSingleton<LLViewerStatsRecorder>
{ {
public: public:
LOG_CLASS(LLViewerStatsRecorder);
LLViewerStatsRecorder(); LLViewerStatsRecorder();
~LLViewerStatsRecorder(); ~LLViewerStatsRecorder();
static void initClass(); void objectUpdateFailure(U32 local_id, const EObjectUpdateType update_type, S32 msg_size)
static void cleanupClass(); {
static LLViewerStatsRecorder* instance() {return sInstance; } #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 objectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp, S32 msg_size)
void recordObjectUpdateFailure(U32 local_id, const EObjectUpdateType update_type); {
void recordCacheMissEvent(U32 local_id, const EObjectUpdateType update_type, U8 cache_miss_type); #if LL_RECORD_VIEWER_STATS
void recordObjectUpdateEvent(U32 local_id, const EObjectUpdateType update_type, LLViewerObject * objectp); recordObjectUpdateEvent(local_id, update_type, objectp, msg_size);
void recordCacheFullUpdate(U32 local_id, const EObjectUpdateType update_type, LLViewerRegion::eCacheUpdateResult update_result, LLViewerObject* objectp); #endif
void recordRequestCacheMissesEvent(S32 count); }
void endObjectUpdateEvents();
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(); F32 getTimeSinceStart();
private: 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; static LLViewerStatsRecorder* sInstance;
LLFILE * mObjectCacheFile; // File to write data into LLFILE * mObjectCacheFile; // File to write data into
LLFrameTimer mTimer; LLFrameTimer mTimer;
LLViewerRegion* mRegionp;
F64 mStartTime; F64 mStartTime;
F64 mProcessingTime; F64 mLastSnapshotTime;
S32 mObjectCacheHitCount; S32 mObjectCacheHitCount;
S32 mObjectCacheHitSize;
S32 mObjectCacheMissFullCount; S32 mObjectCacheMissFullCount;
S32 mObjectCacheMissFullSize;
S32 mObjectCacheMissCrcCount; S32 mObjectCacheMissCrcCount;
S32 mObjectCacheMissCrcSize;
S32 mObjectFullUpdates; S32 mObjectFullUpdates;
S32 mObjectFullUpdatesSize;
S32 mObjectTerseUpdates; S32 mObjectTerseUpdates;
S32 mObjectTerseUpdatesSize;
S32 mObjectCacheMissRequests; S32 mObjectCacheMissRequests;
S32 mObjectCacheMissResponses; S32 mObjectCacheMissResponses;
S32 mObjectCacheMissResponsesSize;
S32 mObjectCacheUpdateDupes; S32 mObjectCacheUpdateDupes;
S32 mObjectCacheUpdateChanges; S32 mObjectCacheUpdateChanges;
S32 mObjectCacheUpdateAdds; S32 mObjectCacheUpdateAdds;
S32 mObjectCacheUpdateReplacements; S32 mObjectCacheUpdateReplacements;
S32 mObjectUpdateFailures; S32 mObjectUpdateFailures;
S32 mObjectUpdateFailuresSize;
S32 mTextureFetchSize;
void clearStats(); void clearStats();
}; };
#endif // LL_RECORD_VIEWER_STATS
#endif // LLVIEWERSTATSRECORDER_H #endif // LLVIEWERSTATSRECORDER_H

View File

@@ -980,14 +980,6 @@ F32 LLViewerTextureList::updateImagesFetchTextures(F32 max_time)
break; break;
} }
} }
//if (fetch_count == 0)
//{
// gDebugTimers[0].pause();
//}
//else
//{
// gDebugTimers[0].unpause();
//}
return image_op_timer.getElapsedTimeF32(); return image_op_timer.getElapsedTimeF32();
} }

View File

@@ -318,27 +318,24 @@ public:
static const LLCachedControl<bool> debug_show_time("DebugShowTime"); static const LLCachedControl<bool> debug_show_time("DebugShowTime");
if (debug_show_time) if (debug_show_time)
{ {
const U32 y_inc2 = 15;
for (std::map<S32,LLFrameTimer>::reverse_iterator iter = gDebugTimers.rbegin();
iter != gDebugTimers.rend(); ++iter)
{ {
S32 idx = iter->first; const U32 y_inc2 = 15;
LLFrameTimer& timer = iter->second; LLFrameTimer& timer = gTextureTimer;
F32 time = timer.getElapsedTimeF32(); F32 time = timer.getElapsedTimeF32();
S32 hours = (S32)(time / (60*60)); S32 hours = (S32)(time / (60*60));
S32 mins = (S32)((time - hours*(60*60)) / 60); S32 mins = (S32)((time - hours*(60*60)) / 60);
S32 secs = (S32)((time - hours*(60*60) - mins*60)); S32 secs = (S32)((time - hours*(60*60) - mins*60));
std::string label = gDebugTimerLabel[idx]; addText(xpos, ypos, llformat("Texture: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc2;
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;
} }
{
F32 time = gFrameTimeSeconds; F32 time = gFrameTimeSeconds;
S32 hours = (S32)(time / (60*60)); S32 hours = (S32)(time / (60*60));
S32 mins = (S32)((time - hours*(60*60)) / 60); S32 mins = (S32)((time - hours*(60*60)) / 60);
S32 secs = (S32)((time - hours*(60*60) - mins*60)); S32 secs = (S32)((time - hours*(60*60) - mins*60));
addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc; addText(xpos, ypos, llformat("Time: %d:%02d:%02d", hours,mins,secs)); ypos += y_inc;
} }
}
#if LL_WINDOWS #if LL_WINDOWS
static const LLCachedControl<bool> debug_show_memory("DebugShowMemory"); static const LLCachedControl<bool> debug_show_memory("DebugShowMemory");

View File

@@ -567,10 +567,15 @@ SHClientTagMgr::SHClientTagMgr()
gSavedSettings.getControl("AscentFriendColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags)); gSavedSettings.getControl("AscentFriendColor")->getSignal()->connect(boost::bind(&LLVOAvatar::invalidateNameTags));
gSavedSettings.getControl("AscentMutedColor")->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("AscentUseCustomTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this));
gSavedSettings.getControl("AscentCustomTagColor")->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)); 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()) if(!getIsEnabled())
return; return;
@@ -578,12 +583,14 @@ SHClientTagMgr::SHClientTagMgr()
fetchDefinitions(); fetchDefinitions();
parseDefinitions(); parseDefinitions();
//These only matter to the agent avatar. Don't iterate over everything. //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("AscentUseTag")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this)); 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)); gSavedSettings.getControl("AscentReportClientUUID")->getSignal()->connect(boost::bind(&SHClientTagMgr::updateAgentAvatarTag, this));
//Fire off a AgentSetAppearance update if these change. //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("AscentUseTag")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent)); gSavedSettings.getControl("AscentBroadcastTag")->getSignal()->connect(boost::bind(&LLAgent::sendAgentSetAppearance, &gAgent));
gSavedSettings.getControl("AscentReportClientUUID")->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()) if (pAvatar->isSelf())
{ {
static const LLCachedControl<bool> ascent_use_tag("AscentUseTag",true);
static const LLCachedControl<bool> ascent_use_custom_tag("AscentUseCustomTag", false); static const LLCachedControl<bool> ascent_use_custom_tag("AscentUseCustomTag", false);
static const LLCachedControl<LLColor4> ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f)); static const LLCachedControl<LLColor4> ascent_custom_tag_color("AscentCustomTagColor", LLColor4(.5f,1.f,.25f,1.f));
static const LLCachedControl<std::string> ascent_custom_tag_label("AscentCustomTagLabel","custom"); static const LLCachedControl<std::string> ascent_custom_tag_label("AscentCustomTagLabel","custom");
@@ -699,7 +705,7 @@ const LLSD SHClientTagMgr::generateClientTag(const LLVOAvatar* pAvatar) const
{ {
return LLSD(); return LLSD();
} }
else if (ascent_use_tag) else
{ {
id.set(ascent_report_client_uuid,false); id.set(ascent_report_client_uuid,false);
} }
@@ -796,24 +802,32 @@ void SHClientTagMgr::updateAvatarTag(LLVOAvatar* pAvatar)
if(new_tag.isUndefined()) if(new_tag.isUndefined())
mAvatarTags.erase(id); mAvatarTags.erase(id);
else else
mAvatarTags.insert(std::pair<LLUUID,LLSD>(id, new_tag)); mAvatarTags[id]=new_tag;
pAvatar->clearNameTag(); //LLVOAvatar::idleUpdateNameTag will pick up on mNameString being cleared. pAvatar->clearNameTag(); //LLVOAvatar::idleUpdateNameTag will pick up on mNameString being cleared.
} }
} }
const std::string SHClientTagMgr::getClientName(const LLVOAvatar* pAvatar, bool is_friend) const const std::string SHClientTagMgr::getClientName(const LLVOAvatar* pAvatar, bool is_friend) const
{ {
static LLCachedControl<bool> ascent_show_friends_tag("AscentShowFriendsTag", false); static LLCachedControl<bool> ascent_show_friends_tag("AscentShowFriendsTag", false);
static LLCachedControl<bool> ascent_show_self_tag("AscentShowSelfTag", false);
static LLCachedControl<bool> ascent_show_others_tag("AscentShowOthersTag", false);
if(is_friend && ascent_show_friends_tag) if(is_friend && ascent_show_friends_tag)
return "Friend"; return "Friend";
else else
{ {
LLSD tag; if((!pAvatar->isSelf() && ascent_show_others_tag) ||
std::map<LLUUID, LLSD>::const_iterator it = mAvatarTags.find(pAvatar->getID()); (pAvatar->isSelf() && ascent_show_self_tag))
if(it != mAvatarTags.end())
{ {
tag = it->second.get("name"); LLSD tag;
std::map<LLUUID, LLSD>::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 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) while ((index = line.find("%f")) != std::string::npos)
line.replace(index, 2, firstnameText); line.replace(index, 2, firstnameText);
while ((index = line.find("%l")) != std::string::npos) 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) while ((index = line.find("%g")) != std::string::npos)
line.replace(index, 2, groupText); line.replace(index, 2, groupText);
while ((index = line.find("%t")) != std::string::npos) while ((index = line.find("%t")) != std::string::npos)

View File

@@ -2589,7 +2589,7 @@ bool LLVOAvatarSelf::sendAppearanceMessage(LLMessageSystem *mesgsys) const
{ {
LLTextureEntry* entry = getTE((U8) index); LLTextureEntry* entry = getTE((U8) index);
texture_id[index] = entry->getID(); 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"))); entry->setID(LLUUID(gSavedSettings.getString("AscentReportClientUUID")));
else else
entry->setID(IMG_DEFAULT_AVATAR); entry->setID(IMG_DEFAULT_AVATAR);

View File

@@ -926,19 +926,31 @@ void LLVOVolume::sculpt()
if (discard_level > max_discard) if (discard_level > max_discard)
discard_level = max_discard; // clamp to the best we can do 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) if(current_discard < -2)
{ {
llwarns << "WARNING!!: Current discard of sculpty at " << current_discard static S32 low_sculpty_discard_warning_count = 100;
<< " is less than -2." << llendl; 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 // corrupted volume... don't update the sculpty
return; return;
} }
else if (current_discard > MAX_DISCARD_LEVEL) else if (current_discard > MAX_DISCARD_LEVEL)
{ {
llwarns << "WARNING!!: Current discard of sculpty at " << current_discard static S32 high_sculpty_discard_warning_count = 100;
<< " is more than than allowed max of " << MAX_DISCARD_LEVEL << llendl; 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 // corrupted volume... don't update the sculpty
return; return;

View File

@@ -489,7 +489,10 @@ void LLPipeline::init()
//gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings)); //gSavedSettings.getControl("RenderDelayVBUpdate")->getCommitSignal()->connect(boost::bind(&LLPipeline::refreshCachedSettings));
gSavedSettings.getControl("UseOcclusion")->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("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("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() LLPipeline::~LLPipeline()
@@ -631,7 +634,16 @@ void LLPipeline::resizeScreenTexture()
GLuint resX = gViewerWindow->getWorldViewWidthRaw(); GLuint resX = gViewerWindow->getWorldViewWidthRaw();
GLuint resY = gViewerWindow->getWorldViewHeightRaw(); 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") && LLFeatureManager::getInstance()->isFeatureAvailable("UseOcclusion")
&& gSavedSettings.getBOOL("UseOcclusion") && gSavedSettings.getBOOL("UseOcclusion")
&& gGLManager.mHasOcclusionQuery) ? 2 : 0; && gGLManager.mHasOcclusionQuery) ? 2 : 0;
updateRenderDeferred();
} }
void LLPipeline::releaseGLBuffers() void LLPipeline::releaseGLBuffers()
@@ -5412,7 +5426,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
if (light->isLightSpotlight() // directional (spot-)light 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 && (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(); LLQuaternion quat = light->getRenderRotation();
LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction LLVector3 at_axis(0,0,-1); // this matches deferred rendering's object light direction
at_axis *= quat; at_axis *= quat;
@@ -5460,7 +5473,7 @@ void LLPipeline::setupHWLights(LLDrawPool* pool)
F32 light_radius = 16.f; F32 light_radius = 16.f;
F32 x = 3.f; F32 x = 3.f;
float linatten = x / (light_radius); // % of brightness at radius float linatten = x / (light_radius); // % of brightness at radius
mHWLightColors[2] = light_color; mHWLightColors[2] = light_color;
@@ -5624,7 +5637,7 @@ void LLPipeline::enableLightsPreview()
LLVector4 light_pos(dir0, 0.0f); LLVector4 light_pos(dir0, 0.0f);
LLLightState* light = gGL.getLight(0); LLLightState* light = gGL.getLight(1);
light->enable(); light->enable();
light->setPosition(light_pos); light->setPosition(light_pos);
@@ -5636,7 +5649,7 @@ void LLPipeline::enableLightsPreview()
light_pos = LLVector4(dir1, 0.f); light_pos = LLVector4(dir1, 0.f);
light = gGL.getLight(1); light = gGL.getLight(2);
light->enable(); light->enable();
light->setPosition(light_pos); light->setPosition(light_pos);
light->setDiffuse(diffuse1); light->setDiffuse(diffuse1);
@@ -5646,7 +5659,7 @@ void LLPipeline::enableLightsPreview()
light->setSpotCutoff(180.f); light->setSpotCutoff(180.f);
light_pos = LLVector4(dir2, 0.f); light_pos = LLVector4(dir2, 0.f);
light = gGL.getLight(2); light = gGL.getLight(3);
light->enable(); light->enable();
light->setPosition(light_pos); light->setPosition(light_pos);
light->setDiffuse(diffuse2); light->setDiffuse(diffuse2);

View File

@@ -35,6 +35,9 @@
<on_click function="Object.DERENDER" /> <on_click function="Object.DERENDER" />
<on_enable function="Object.EnableDerender" /> <on_enable function="Object.EnableDerender" />
</menu_item_call> </menu_item_call>
<menu_item_call enabled="true" label="Reload" mouse_opaque="true" name="Reload Textures">
<on_click function="Object.ReloadTextures" />
</menu_item_call>
</pie_menu> </pie_menu>
<menu_item_call enabled="true" label="Appearance..." name="Appearance..."> <menu_item_call enabled="true" label="Appearance..." name="Appearance...">
<on_click function="ShowFloater" userdata="appearance" /> <on_click function="ShowFloater" userdata="appearance" />

View File

@@ -14,11 +14,11 @@
</panel> </panel>
<panel border="true" left="1" bottom="-190" height="180" width="500" label="Tags/Colors" name="TagsColors"> <panel border="true" left="1" bottom="-190" height="180" width="500" label="Tags/Colors" name="TagsColors">
<!-- Client tag options --> <!-- Client tag options -->
<check_box bottom_delta="-25" control_name="AscentUseTag" follows="top" height="16" initial_value="true" label="Use Client Tag:" left="10" tool_tip="Enabling this will show your client tag on your avatar name locally." name="show_my_tag_check"/> <check_box bottom_delta="-25" control_name="AscentBroadcastTag" follows="top" height="16" initial_value="true" label="Broadcast Client Tag:" left="10" tool_tip="Choose whether others see that you enjoy Singularity." name="show_my_tag_check"/>
<combo_box follows="top" bottom_delta="-24" height="18" left_delta="24" max_chars="32" tool_tip="The client tag (And subsequent color) to broadcast. Overridden locally by Custom Tag/Color." name="tag_spoofing_combobox" width="130"> <combo_box follows="top" bottom_delta="-24" height="18" left_delta="24" max_chars="32" tool_tip="The client tag (And subsequent color) to broadcast. Overridden locally by Custom Tag/Color." name="tag_spoofing_combobox" width="130">
<combo_item name="Singularity" value="f25263b7-6167-4f34-a4ef-af65213b2e39">Singularity</combo_item> <combo_item name="Singularity" value="f25263b7-6167-4f34-a4ef-af65213b2e39">Singularity</combo_item>
</combo_box> </combo_box>
<check_box bottom_delta="-23" control_name="AscentShowSelfTag" follows="top" height="16" initial_value="true" label="Display client tag to self" left_delta="-24" tool_tip="Choose whether others see that you enjoy Singularity." name="show_self_tag_check"/> <check_box bottom_delta="-23" control_name="AscentShowSelfTag" follows="top" height="16" initial_value="true" label="Display client tag to self" left_delta="-24" tool_tip="Enabling this will show your client tag on your avatar name locally." name="show_self_tag_check"/>
<check_box bottom_delta="-20" control_name="AscentShowSelfTagColor" follows="top" height="16" initial_value="true" label="Display client tag color to self" tool_tip="Enabling this set your avatar name color to your client tag color or custom set color." name="show_self_tag_color_check"/> <check_box bottom_delta="-20" control_name="AscentShowSelfTagColor" follows="top" height="16" initial_value="true" label="Display client tag color to self" tool_tip="Enabling this set your avatar name color to your client tag color or custom set color." name="show_self_tag_color_check"/>
<check_box bottom_delta="-20" control_name="AscentShowFriendsTag" follows="top" height="16" initial_value="true" label="Display friend client tags as (Friend)" tool_tip="Enabling this changes your friends' client tags to (Friend)." name="show_friend_tag_check"/> <check_box bottom_delta="-20" control_name="AscentShowFriendsTag" follows="top" height="16" initial_value="true" label="Display friend client tags as (Friend)" tool_tip="Enabling this changes your friends' client tags to (Friend)." name="show_friend_tag_check"/>
<!-- End of Left Side --> <!-- End of Left Side -->

View File

@@ -1908,7 +1908,7 @@ Requests that a nonphysical object be keyframed according to keyframe list.
</string> </string>
<string name="LSLTipText_llTransferLindenDollars"> <string name="LSLTipText_llTransferLindenDollars">
key llTransferLindenDollars(key destination, integer amount) 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> </string>
<string name="LSLTipText_llGetParcelMusicURL"> <string name="LSLTipText_llGetParcelMusicURL">
string llGetParcelMusicURL() string llGetParcelMusicURL()
@@ -4005,16 +4005,16 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Home position set.">Home position set.</string> <string name="Home position set.">Home position set.</string>
<!-- Financial operations strings --> <!-- Financial operations strings -->
<string name="paid_you_ldollars">[NAME] paid you L$[AMOUNT] [REASON].</string> <string name="paid_you_ldollars">[NAME] paid you [CURRENCY][AMOUNT] [REASON].</string>
<string name="paid_you_ldollars_no_reason">[NAME] paid you L$[AMOUNT].</string> <string name="paid_you_ldollars_no_reason">[NAME] paid you [CURRENCY][AMOUNT].</string>
<string name="you_paid_ldollars">You paid [NAME] L$[AMOUNT] [REASON].</string> <string name="you_paid_ldollars">You paid [NAME] [CURRENCY][AMOUNT] [REASON].</string>
<string name="you_paid_ldollars_no_info">You paid L$[AMOUNT].</string> <string name="you_paid_ldollars_no_info">You paid [CURRENCY][AMOUNT].</string>
<string name="you_paid_ldollars_no_reason">You paid [NAME] L$[AMOUNT].</string> <string name="you_paid_ldollars_no_reason">You paid [NAME] [CURRENCY][AMOUNT].</string>
<string name="you_paid_ldollars_no_name">You paid L$[AMOUNT] [REASON].</string> <string name="you_paid_ldollars_no_name">You paid [CURRENCY][AMOUNT] [REASON].</string>
<string name="you_paid_failure_ldollars">You failed to pay [NAME] L$[AMOUNT] [REASON].</string> <string name="you_paid_failure_ldollars">You failed to pay [NAME] [CURRENCY][AMOUNT] [REASON].</string>
<string name="you_paid_failure_ldollars_no_info">You failed to pay L$[AMOUNT].</string> <string name="you_paid_failure_ldollars_no_info">You failed to pay [CURRENCY][AMOUNT].</string>
<string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] L$[AMOUNT].</string> <string name="you_paid_failure_ldollars_no_reason">You failed to pay [NAME] [CURRENCY][AMOUNT].</string>
<string name="you_paid_failure_ldollars_no_name">You failed to pay L$[AMOUNT] [REASON].</string> <string name="you_paid_failure_ldollars_no_name">You failed to pay [CURRENCY][AMOUNT] [REASON].</string>
<string name="for item">for [ITEM]</string> <string name="for item">for [ITEM]</string>
<string name="for a parcel of land">for a parcel of land</string> <string name="for a parcel of land">for a parcel of land</string>
<string name="for a land access pass">for a land access pass</string> <string name="for a land access pass">for a land access pass</string>