[sldev] [VIEWER] Memory Usage / Animations
Nicholaz Beresford
nicholaz at blueflash.cc
Tue Sep 4 05:32:00 PDT 2007
I applied little wizardry to my leak dump routines for visual studio
yesterday, allowing me to get a heap snapshot while the program runs,
spitting out a list of places in the source which have the memory
allocated on the heap and sorting them by size.
I was going to a busy sim (Bad Girls) and found that (besides textures)
the biggest memory spenders were llpointerskipmap, llpolymesh and
keyframemotion (not entirely surprising in a place with 30-50 avatars
dancing).
There's a construct called llkeyframemotioncache which I discovered
previously, which caches keyframemotions, but never clears them. I have
a patch (see VWR-1769) which clears this cache on teleports, but
unfortunately it's broken (or collides) by something that appeared in
1.18.1, leading to crashes after teleport (I think it was planned to go
into a recent release but was backed out because of the collision).
The Linden change also seems to produce new leaks (my own viewer runs
normally practically with no mmory left over when it exits), even when
not colliding with my VWR-1769, so somethig seems fishy there.
I also have a patch from Soft, refcounting LLMotion, which counter the
effects, but I'm not sure if it fixes the collision and leaks entirely
(doing test runs is a bit awkward, as they depend on what other avatars do).
*
Well, long story short: The llkeyframemotion cache needs some attention
as it eats a lot of memory in busy sims. 30 minutes at Bad Girls or a
similar sim can cost up to 50MB-100MB which never get freed until you
log off with (literally) a million of small heap blocks.
If you have your own builds you may be interested in this:
Builds based on 1.16.0.8 can apply the 1769 from the JIRA (it's tried
and trusted, runs on my viewer build for a long time now) to get the
cache flushed on teleports.
If you have a build based on voice (1.18.1 or later) you need to apply
(reverse) the attached llmotion patch if you want to run with VWR-1769.
And I'm attaching a newer version of VWR-1769 which expires entries from
the cache while staying on a sim. That one is pretty new and more
beta'ish, so it could use some eyeballs or comments. On the other hand,
one of my users who is a manager at Bad Girls and stays there for
hours, was running it with my voice viewer and very good results yesterday.
Nick
-------------- next part --------------
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llmotion.cpp sl1_18_2_0\linden-orig\indra/llcharacter/llmotion.cpp
--- linden/indra/llcharacter/llmotion.cpp 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llmotion.cpp 2007-08-10 10:39:40.000000000 +0200
@@ -126,6 +126,11 @@
mDeactivateCallbackUserData = userdata;
}
+BOOL LLMotion::isBlending()
+{
+ return mPose.getWeight() < 1.f;
+}
+
//-----------------------------------------------------------------------------
// activate()
//-----------------------------------------------------------------------------
@@ -142,10 +147,16 @@
void LLMotion::deactivate()
{
mActive = FALSE;
+ mPose.setWeight(0.f);
if (mDeactivateCallback) (*mDeactivateCallback)(mDeactivateCallbackUserData);
onDeactivate();
}
+BOOL LLMotion::canDeprecate()
+{
+ return TRUE;
+}
+
// End
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llmotion.h sl1_18_2_0\linden-orig\indra/llcharacter/llmotion.h
--- linden/indra/llcharacter/llmotion.h 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llmotion.h 2007-08-10 10:39:40.000000000 +0200
@@ -99,13 +99,14 @@
void setStopped(BOOL stopped) { mStopped = stopped; }
+ BOOL isBlending();
+
void activate();
void deactivate();
BOOL isActive() { return mActive; }
-
public:
//-------------------------------------------------------------------------
// animation callbacks to be implemented by subclasses
@@ -145,6 +146,11 @@
// called when a motion is deactivated
virtual void onDeactivate() = 0;
+ // can we crossfade this motion with a new instance when restarted?
+ // should ultimately always be TRUE, but lack of emote blending, etc
+ // requires this
+ virtual BOOL canDeprecate();
+
// optional callback routine called when animation deactivated.
void setDeactivateCallback( void (*cb)(void *), void* userdata );
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llmotioncontroller.cpp sl1_18_2_0\linden-orig\indra/llcharacter/llmotioncontroller.cpp
--- linden/indra/llcharacter/llmotioncontroller.cpp 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llmotioncontroller.cpp 2007-08-10 10:39:40.000000000 +0200
@@ -194,34 +194,44 @@
//-----------------------------------------------------------------------------
void LLMotionController::addLoadedMotion(LLMotion* motionp)
{
+ std::set<LLUUID> motions_to_kill;
+
+ // gather all inactive, loaded motions
if (mLoadedMotions.size() > MAX_MOTION_INSTANCES)
{
// too many motions active this frame, kill all blenders
mPoseBlender.clearBlenders();
- for (U32 i = 0; i < mLoadedMotions.size(); i++)
+ for (motion_list_t::iterator loaded_motion_it = mLoadedMotions.begin();
+ loaded_motion_it != mLoadedMotions.end();
+ ++loaded_motion_it)
{
- LLMotion* cur_motionp = mLoadedMotions.front();
- mLoadedMotions.pop_front();
+ LLMotion* cur_motionp = *loaded_motion_it;
// motion isn't playing, delete it
if (!isMotionActive(cur_motionp))
{
- mCharacter->requestStopMotion(cur_motionp);
- mAllMotions.erase(cur_motionp->getID());
- delete cur_motionp;
- if (mLoadedMotions.size() <= MAX_MOTION_INSTANCES)
- {
- break;
- }
- }
- else
- {
- // put active motion on back
- mLoadedMotions.push_back(cur_motionp);
+ motions_to_kill.insert(cur_motionp->getID());
}
}
}
+
+ // clean up all inactive, loaded motions
+ for (std::set<LLUUID>::iterator motion_it = motions_to_kill.begin();
+ motion_it != motions_to_kill.end();
+ ++motion_it)
+ {
+ // look up the motion again by ID to get canonical instance
+ // and kill it only if that one is inactive
+ LLUUID motion_id = *motion_it;
+ LLMotion* motionp = findMotion(motion_id);
+ if (motionp && !isMotionActive(motionp))
+ {
+ removeMotion(motion_id);
+ }
+ }
+
+ // add new motion to loaded list
mLoadedMotions.push_back(motionp);
}
@@ -280,14 +290,24 @@
void LLMotionController::removeMotion( const LLUUID& id)
{
LLMotion* motionp = findMotion(id);
+
+ removeMotionInstance(motionp);
+
+ mAllMotions.erase(id);
+}
+
+// removes instance of a motion from all runtime structures, but does
+// not erase entry by ID, as this could be a duplicate instance
+// use removeMotion(id) to remove all references to a given motion by id.
+void LLMotionController::removeMotionInstance(LLMotion* motionp)
+{
if (motionp)
{
- stopMotionLocally(id, TRUE);
+ stopMotionInstance(motionp, TRUE);
mLoadingMotions.erase(motionp);
mLoadedMotions.remove(motionp);
mActiveMotions.remove(motionp);
- mAllMotions.erase(id);
delete motionp;
}
}
@@ -348,28 +368,39 @@
//-----------------------------------------------------------------------------
BOOL LLMotionController::startMotion(const LLUUID &id, F32 start_offset)
{
- // look for motion in our list of created motions
- LLMotion *motion = createMotion(id);
+ // do we have an instance of this motion for this character?
+ LLMotion *motion = findMotion(id);
+
+ // motion that is stopping will be allowed to stop but
+ // replaced by a new instance of that motion
+ if (motion
+ && motion->canDeprecate()
+ && motion->getFadeWeight() > 0.01f // not LOD-ed out
+ && (motion->isBlending() || motion->getStopTime() != 0.f))
+ {
+ deprecateMotionInstance(motion);
+ // force creation of new instance
+ motion = NULL;
+ }
+
+ // create new motion instance
+ if (!motion)
+ {
+ motion = createMotion(id);
+ }
if (!motion)
{
return FALSE;
}
- //if the motion is already active, then we're done
- else if (isMotionActive(motion)) // motion is playing and...
+ //if the motion is already active and allows deprecation, then let it keep playing
+ else if (motion->canDeprecate() && isMotionActive(motion))
{
- if (motion->isStopped()) // motion has been stopped
- {
- deactivateMotion(motion, false);
- }
- else if (mTime < motion->mSendStopTimestamp) // motion is still active
- {
- return TRUE;
- }
+ return TRUE;
}
// llinfos << "Starting motion " << name << llendl;
- return activateMotion(motion, mTime - start_offset);
+ return activateMotionInstance(motion, mTime - start_offset);
}
@@ -380,6 +411,12 @@
{
// if already inactive, return false
LLMotion *motion = findMotion(id);
+
+ return stopMotionInstance(motion, stop_immediate);
+}
+
+BOOL LLMotionController::stopMotionInstance(LLMotion* motion, BOOL stop_immediate)
+{
if (!motion)
{
return FALSE;
@@ -396,7 +433,7 @@
if (stop_immediate)
{
- deactivateMotion(motion, false);
+ deactivateMotionInstance(motion);
}
return TRUE;
}
@@ -492,7 +529,7 @@
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, false);
+ deactivateMotionInstance(motionp);
}
else if (motionp->isStopped() && mTime > motionp->getStopTime())
{
@@ -510,7 +547,7 @@
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
else if (mTime >= motionp->mActivationTimestamp)
@@ -538,7 +575,7 @@
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -546,7 +583,8 @@
{
if (motionp->isStopped() && mTime > motionp->getStopTime() + motionp->getEaseOutDuration())
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
}
continue;
}
@@ -572,7 +610,8 @@
}
else
{
- deactivateMotion(motionp, true);
+ posep->setWeight(0.f);
+ deactivateMotionInstance(motionp);
continue;
}
}
@@ -617,7 +656,7 @@
if (mLastTime <= motionp->mSendStopTimestamp)
{
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -661,7 +700,7 @@
// propagate this to the network
// as not all viewers are guaranteed to have access to the same logic
mCharacter->requestStopMotion( motionp );
- stopMotionLocally(motionp->getID(), FALSE);
+ stopMotionInstance(motionp, FALSE);
}
}
@@ -733,7 +772,7 @@
// this motion should be playing
if (!motionp->isStopped())
{
- activateMotion(motionp, mTime);
+ activateMotionInstance(motionp, mTime);
}
}
else if (status == LLMotion::STATUS_FAILURE)
@@ -741,6 +780,7 @@
llinfos << "Motion " << motionp->getID() << " init failed." << llendl;
sRegistry.markBad(motionp->getID());
mLoadingMotions.erase(curiter);
+
mAllMotions.erase(motionp->getID());
delete motionp;
}
@@ -773,9 +813,9 @@
//-----------------------------------------------------------------------------
-// activateMotion()
+// activateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::activateMotion(LLMotion *motion, F32 time)
+BOOL LLMotionController::activateMotionInstance(LLMotion *motion, F32 time)
{
if (mLoadingMotions.find(motion) != mLoadingMotions.end())
{
@@ -818,23 +858,38 @@
}
//-----------------------------------------------------------------------------
-// deactivateMotion()
+// deactivateMotionInstance()
//-----------------------------------------------------------------------------
-BOOL LLMotionController::deactivateMotion(LLMotion *motion, bool remove_weight)
+BOOL LLMotionController::deactivateMotionInstance(LLMotion *motion)
{
- if( remove_weight )
+ motion->deactivate();
+
+ motion_set_t::iterator found_it = mDeprecatedMotions.find(motion);
+ if (found_it != mDeprecatedMotions.end())
{
- // immediately remove pose weighting instead of letting it time out
- LLPose *posep = motion->getPose();
- posep->setWeight(0.f);
+ // deprecated motions need to be completely excised
+ removeMotionInstance(motion);
+ mDeprecatedMotions.erase(found_it);
+ }
+ else
+ {
+ // for motions that we are keeping, simply remove from active queue
+ mActiveMotions.remove(motion);
}
-
- motion->deactivate();
- mActiveMotions.remove(motion);
return TRUE;
}
+void LLMotionController::deprecateMotionInstance(LLMotion* motion)
+{
+ mDeprecatedMotions.insert(motion);
+
+ //fade out deprecated motion
+ stopMotionInstance(motion, FALSE);
+ //no longer canonical
+ mAllMotions.erase(motion->getID());
+}
+
//-----------------------------------------------------------------------------
// isMotionActive()
//-----------------------------------------------------------------------------
@@ -857,7 +912,7 @@
//-----------------------------------------------------------------------------
LLMotion *LLMotionController::findMotion(const LLUUID& id)
{
- return mAllMotions[id];
+ return get_if_there<LLUUID, LLMotion*>(mAllMotions, id, NULL);
}
//-----------------------------------------------------------------------------
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llmotioncontroller.h sl1_18_2_0\linden-orig\indra/llcharacter/llmotioncontroller.h
--- linden/indra/llcharacter/llmotioncontroller.h 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llmotioncontroller.h 2007-08-10 10:39:40.000000000 +0200
@@ -179,16 +179,21 @@
LLMotion *findMotion( const LLUUID& id );
protected:
+ // internal operations act on motion instances directly
+ // as there can be duplicate motions per id during blending overlap
void deleteAllMotions();
void addLoadedMotion(LLMotion *motion);
- BOOL activateMotion(LLMotion *motion, F32 time);
- BOOL deactivateMotion(LLMotion *motion, bool remove_weight);
+ BOOL activateMotionInstance(LLMotion *motion, F32 time);
+ BOOL deactivateMotionInstance(LLMotion *motion);
+ void deprecateMotionInstance(LLMotion* motion);
+ BOOL stopMotionInstance(LLMotion *motion, BOOL stop_imemdiate);
+ void removeMotionInstance(LLMotion* motion);
void updateRegularMotions();
void updateAdditiveMotions();
void resetJointSignatures();
void updateMotionsByType(LLMotion::LLMotionBlendType motion_type);
-protected:
+protected:
F32 mTimeFactor;
static LLMotionRegistry sRegistry;
LLPoseBlender mPoseBlender;
@@ -203,11 +208,13 @@
// Once an animations is loaded, it will be initialized and put on the mLoadedMotions deque.
// Any animation that is currently playing also sits in the mActiveMotions list.
- std::map<LLUUID, LLMotion*> mAllMotions;
+ typedef std::map<LLUUID, LLMotion*> motion_map_t;
+ motion_map_t mAllMotions;
motion_set_t mLoadingMotions;
motion_list_t mLoadedMotions;
motion_list_t mActiveMotions;
+ motion_set_t mDeprecatedMotions;
LLFrameTimer mTimer;
F32 mTime;
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llpose.cpp sl1_18_2_0\linden-orig\indra/llcharacter/llpose.cpp
--- linden/indra/llcharacter/llpose.cpp 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llpose.cpp 2007-08-10 10:39:40.000000000 +0200
@@ -275,9 +275,9 @@
joint_state_index < JSB_NUM_JOINT_STATES && mJointStates[joint_state_index] != NULL;
joint_state_index++)
{
- U32 current_usage = mJointStates[joint_state_index]->getUsage();
- F32 current_weight = mJointStates[joint_state_index]->getWeight();
LLJointState* jsp = mJointStates[joint_state_index];
+ U32 current_usage = jsp->getUsage();
+ F32 current_weight = jsp->getWeight();
if (current_weight == 0.f)
{
@@ -292,17 +292,14 @@
// add in pos for this jointstate modulated by weight
added_pos += jsp->getPosition() * (new_weight_sum - sum_weights[POS_WEIGHT]);
- //sum_weights[POS_WEIGHT] = new_weight_sum;
}
- // now do scale
if(current_usage & LLJointState::SCALE)
{
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// add in scale for this jointstate modulated by weight
added_scale += jsp->getScale() * (new_weight_sum - sum_weights[SCALE_WEIGHT]);
- //sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
if (current_usage & LLJointState::ROT)
@@ -311,7 +308,6 @@
// add in rotation for this jointstate modulated by weight
added_rot = nlerp((new_weight_sum - sum_weights[ROT_WEIGHT]), added_rot, jsp->getRotation()) * added_rot;
- //sum_weights[ROT_WEIGHT] = new_weight_sum;
}
}
else
@@ -326,13 +322,13 @@
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[POS_WEIGHT]);
// blend positions from both
- blended_pos = lerp(mJointStates[joint_state_index]->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
+ blended_pos = lerp(jsp->getPosition(), blended_pos, sum_weights[POS_WEIGHT] / new_weight_sum);
sum_weights[POS_WEIGHT] = new_weight_sum;
}
else
{
// copy position from current
- blended_pos = mJointStates[joint_state_index]->getPosition();
+ blended_pos = jsp->getPosition();
sum_weights[POS_WEIGHT] = current_weight;
}
}
@@ -345,13 +341,13 @@
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[SCALE_WEIGHT]);
// blend scales from both
- blended_scale = lerp(mJointStates[joint_state_index]->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
+ blended_scale = lerp(jsp->getScale(), blended_scale, sum_weights[SCALE_WEIGHT] / new_weight_sum);
sum_weights[SCALE_WEIGHT] = new_weight_sum;
}
else
{
// copy scale from current
- blended_scale = mJointStates[joint_state_index]->getScale();
+ blended_scale = jsp->getScale();
sum_weights[SCALE_WEIGHT] = current_weight;
}
}
@@ -364,13 +360,13 @@
F32 new_weight_sum = llmin(1.f, current_weight + sum_weights[ROT_WEIGHT]);
// blend rotations from both
- blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, mJointStates[joint_state_index]->getRotation(), blended_rot);
+ blended_rot = nlerp(sum_weights[ROT_WEIGHT] / new_weight_sum, jsp->getRotation(), blended_rot);
sum_weights[ROT_WEIGHT] = new_weight_sum;
}
else
{
// copy rotation from current
- blended_rot = mJointStates[joint_state_index]->getRotation();
+ blended_rot = jsp->getRotation();
sum_weights[ROT_WEIGHT] = current_weight;
}
}
diff -urN -X srcdiff.ind --strip-trailing-cr linden/indra/llcharacter/llpose.h sl1_18_2_0\linden-orig\indra/llcharacter/llpose.h
--- linden/indra/llcharacter/llpose.h 2007-07-11 15:19:44.000000000 +0200
+++ linden/indra/llcharacter/llpose.h 2007-08-10 10:39:40.000000000 +0200
@@ -81,7 +81,7 @@
S32 getNumJointStates() const;
};
-const S32 JSB_NUM_JOINT_STATES = 4;
+const S32 JSB_NUM_JOINT_STATES = 6;
class LLJointStateBlender
{
-------------- next part --------------
--- linden-orig/indra/llcharacter/llkeyframemotion.h 2007-08-29 14:13:04.000000000 +0200
+++ linden/indra/llcharacter/llkeyframemotion.h 2007-09-04 00:58:44.656250000 +0200
@@ -40,6 +40,7 @@
#include "llhandmotion.h"
#include "lljointstate.h"
#include "llmotion.h"
+#include "llmemory.h"
#include "llptrskipmap.h"
#include "llquaternion.h"
#include "v3dmath.h"
@@ -151,7 +152,7 @@
BOOL serialize(LLDataPacker& dp) const;
BOOL deserialize(LLDataPacker& dp);
void writeCAL3D(apr_file_t* fp);
- BOOL isLoaded() { return mJointMotionList != NULL; }
+ BOOL isLoaded() { return mJointMotionList.notNull(); }
// setters for modifying a keyframe animation
@@ -391,10 +392,14 @@
//-------------------------------------------------------------------------
// JointMotionList
//-------------------------------------------------------------------------
- class JointMotionList
+ class JointMotionList : public LLRefCount
{
+ protected:
+ ~JointMotionList();
+
public:
U32 mNumJointMotions;
+ U64 mTimeLastCacheHit;
JointMotion* mJointMotionArray;
F32 mDuration;
BOOL mLoop;
@@ -410,7 +415,6 @@
LLBBoxLocal mPelvisBBox;
public:
JointMotionList();
- ~JointMotionList();
U32 dumpDiagInfo();
};
@@ -421,7 +425,7 @@
//-------------------------------------------------------------------------
// Member Data
//-------------------------------------------------------------------------
- JointMotionList* mJointMotionList;
+ LLPointer<JointMotionList> mJointMotionList;
LLJointState* mJointStates;
LLJoint* mPelvisp;
LLCharacter* mCharacter;
@@ -441,13 +445,16 @@
LLKeyframeDataCache(){};
~LLKeyframeDataCache();
- typedef std::map<LLUUID, class LLKeyframeMotion::JointMotionList*> keyframe_data_map_t;
+ typedef std::map<LLUUID, LLPointer<class LLKeyframeMotion::JointMotionList> > keyframe_data_map_t;
static keyframe_data_map_t sKeyframeDataMap;
+ static U64 sLastCacheCleanup;
+
static void addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList*);
static LLKeyframeMotion::JointMotionList* getKeyframeData(const LLUUID& id);
static void removeKeyframeData(const LLUUID& id);
+ static void cleanupCache(int maxage = 0);
//print out diagnostic info
static void dumpDiagInfo();
--- linden-orig/indra/llcharacter/llkeyframemotion.cpp 2007-08-29 14:13:04.000000000 +0200
+++ linden/indra/llcharacter/llkeyframemotion.cpp 2007-09-04 01:43:02.343750000 +0200
@@ -42,6 +42,7 @@
#include "llkeyframemotion.h"
#include "llquantize.h"
#include "llvfile.h"
+#include "lltimer.h"
#include "m3math.h"
#include "message.h"
@@ -50,6 +51,8 @@
//-----------------------------------------------------------------------------
LLVFS* LLKeyframeMotion::sVFS = NULL;
LLKeyframeDataCache::keyframe_data_map_t LLKeyframeDataCache::sKeyframeDataMap;
+U64 LLKeyframeDataCache::sLastCacheCleanup;
+
//-----------------------------------------------------------------------------
// Globals
@@ -69,6 +72,7 @@
//-----------------------------------------------------------------------------
LLKeyframeMotion::JointMotionList::JointMotionList()
: mNumJointMotions(0),
+ mTimeLastCacheHit(0),
mJointMotionArray(NULL)
{
}
@@ -1858,8 +1862,7 @@
//-----------------------------------------------------------------------------
void LLKeyframeMotion::flushKeyframeCache()
{
- // TODO: Make this safe to do
-// LLKeyframeDataCache::clear();
+ LLKeyframeDataCache::clear();
}
//-----------------------------------------------------------------------------
@@ -2102,6 +2105,7 @@
//--------------------------------------------------------------------
void LLKeyframeDataCache::addKeyframeData(const LLUUID& id, LLKeyframeMotion::JointMotionList* joint_motion_listp)
{
+ joint_motion_listp->mTimeLastCacheHit = (U64)LLTimer::getTotalSeconds();
sKeyframeDataMap[id] = joint_motion_listp;
}
@@ -2113,7 +2117,6 @@
keyframe_data_map_t::iterator found_data = sKeyframeDataMap.find(id);
if (found_data != sKeyframeDataMap.end())
{
- delete found_data->second;
sKeyframeDataMap.erase(found_data);
}
}
@@ -2128,6 +2131,11 @@
{
return NULL;
}
+
+ found_data->second->mTimeLastCacheHit = (U64)LLTimer::getTotalSeconds();
+
+ cleanupCache();
+
return found_data->second;
}
@@ -2139,12 +2147,72 @@
clear();
}
+
+//-----------------------------------------------------------------------------
+// flush older entries
+//-----------------------------------------------------------------------------
+void LLKeyframeDataCache::cleanupCache(S32 maxage)
+{
+ U64 now = (U64)LLTimer::getTotalSeconds();
+
+ if (0 == sLastCacheCleanup)
+ {
+ sLastCacheCleanup = now;
+ return;
+ }
+
+ if (now-sLastCacheCleanup > 60 || maxage != 0)
+ {
+ S32 count = sKeyframeDataMap.size();
+ S32 deleted = 0;
+
+ if (0 == maxage) {
+ // lifetime of 30 min - 5 min depending on #of entries (0 - 250+)
+ maxage = 60 * (S32)(30.f - llclamp((F32)count/10, 0.f, 25.f));
+ }
+
+ llinfos << "before: " << count << " entries, flushing with maxage " << maxage << llendl;
+
+ for (keyframe_data_map_t::iterator map_it = sKeyframeDataMap.begin();
+ map_it != sKeyframeDataMap.end();
+ )
+ {
+ LLPointer<LLKeyframeMotion::JointMotionList> motion_list_p = map_it->second;
+
+ U64 age = now - motion_list_p->mTimeLastCacheHit;
+ if (age > maxage)
+ {
+ llinfos << " erasing JointMotionList "
+ << map_it->first
+ << " from sKeyframeDataMap"
+ << llendl;
+ keyframe_data_map_t::iterator tmp_it = map_it;
+ ++map_it;
+ sKeyframeDataMap.erase(tmp_it);
+ deleted++;
+ }
+ else
+ {
+ ++map_it;
+ }
+ }
+
+ if (deleted>0)
+ {
+ llinfos << "after: " << sKeyframeDataMap.size() << " (-" << deleted << ") entries " << llendl;
+ }
+
+ sLastCacheCleanup = now;
+ }
+
+}
+
//-----------------------------------------------------------------------------
// clear()
//-----------------------------------------------------------------------------
void LLKeyframeDataCache::clear()
{
- for_each(sKeyframeDataMap.begin(), sKeyframeDataMap.end(), DeletePairedPointer());
+ // dumpDiagInfo();
sKeyframeDataMap.clear();
}
--- linden-orig/indra/newview/llviewermessage.cpp 2007-08-29 14:13:08.000000000 +0200
+++ linden/indra/newview/llviewermessage.cpp 2007-09-04 02:05:20.234375000 +0200
@@ -93,6 +93,7 @@
#include "llimpanel.h"
#include "llinventorymodel.h"
#include "llinventoryview.h"
+#include "llkeyframemotion.h"
#include "llmenugl.h"
#include "llmutelist.h"
#include "llnetmap.h"
@@ -1189,9 +1190,17 @@
return;
}
+ // NICHOLAZ: KLUDGE to unclutter the server side message
+ LLString::format_map_t repl;
+ LLString msg = info->mDesc;
+ repl[" ( http://slurl.com/secondlife/"] = "(";
+ repl[" )"] = ")";
+ LLString::format(msg, repl);
+
LLString::format_map_t args;
- args["[OBJECTNAME]"] = info->mDesc;
+ args["[OBJECTNAME]"] = msg;
args["[OBJECTTYPE]"] = LLAssetType::lookupHumanReadable(info->mType);
+ // ~NICHOLAZ
// Name cache callbacks don't store userdata, so can't save
// off the LLOfferInfo. Argh. JC
@@ -2714,6 +2723,8 @@
llinfos << "Changing home region to " << x << ":" << y << llendl;
+ LLKeyframeDataCache::cleanupCache(60);
+
// set our upstream host the new simulator and shuffle things as
// appropriate.
LLVector3 shift_vector = regionp->getPosRegionFromGlobal(
More information about the SLDev
mailing list