diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 4d5b0c62e4251ba6e52433a4762231315f794595..29427bbaa3db5ff5115e613924a2aefc086dbf0a 100755
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -4590,6 +4590,17 @@
       <key>Value</key>
       <integer>0</integer>
     </map>
+    <key>InvisibleObjectsInMemoryTime</key>
+    <map>
+      <key>Comment</key>
+      <string>Number of frames invisible objects stay in memory before being removed. 0 means never to remove.</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>64</integer>
+    </map>
     <key>JoystickAvatarEnabled</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp
index 8430c325512c5876fad4cc363be10950ac1da478..8587c7852b3e5ed05e8479211c0f83c9007a81eb 100755
--- a/indra/newview/lldrawable.cpp
+++ b/indra/newview/lldrawable.cpp
@@ -1098,9 +1098,9 @@ LLSpatialPartition* LLDrawable::getSpatialPartition()
 }
 
 //virtual
-S32 LLDrawable::getMinFrameRange() const
+U32 LLDrawable::getMinFrameRange() const
 {
-const S32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
+	const U32 MIN_VIS_FRAME_RANGE = 2 ; //two frames:the current one and the last one.
 
 	return MIN_VIS_FRAME_RANGE ;
 }
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 98f0b51a9753436ae95b871d99224cb4d687bef3..ebda18861814554761f72f62b14c2d31dc1fe542 100755
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -193,7 +193,7 @@ class LLDrawable
 
 	LLSpatialPartition* getSpatialPartition();
 	
-	virtual S32 getMinFrameRange()const;
+	virtual U32 getMinFrameRange()const;
 	void removeFromOctree();
 
 	void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; }
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 45130efeb9fa0dfb1570a6fe03d2417441f97898..b9d4c016c27cd62e21524adee552ef90e1fef78d 100755
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -841,11 +841,16 @@ void LLSpatialGroup::handleRemoval(const TreeNode* node, LLViewerOctreeEntry* en
 
 void LLSpatialGroup::handleDestruction(const TreeNode* node)
 {
+	if(isDead())
+	{
+		return;
+	}
 	setState(DEAD);
 	
-	for (element_iter i = getDataBegin(); i != getDataEnd(); ++i)
+	for (element_iter i = getDataBegin(); getElementCount() > 0 && i != getDataEnd();)
 	{
 		LLViewerOctreeEntry* entry = *i;
+
 		if (entry->getGroup() == this)
 		{
 			if(entry->hasDrawable())
@@ -853,10 +858,14 @@ void LLSpatialGroup::handleDestruction(const TreeNode* node)
 				((LLDrawable*)entry->getDrawable())->setGroup(NULL);
 			}
 			else
-		{
+			{
 				llerrs << "No Drawable found in the entry." << llendl;
 			}
 		}
+		else
+		{
+			++i;
+		}
 	}
 	
 	//clean up avatar attachment stats
diff --git a/indra/newview/llvieweroctree.h b/indra/newview/llvieweroctree.h
index 0a96676be100211a0bef722711a731bdb9ceee83..7f2ca6ed2d47d610ec71fa68dd4c304fa47c3a41 100644
--- a/indra/newview/llvieweroctree.h
+++ b/indra/newview/llvieweroctree.h
@@ -149,7 +149,7 @@ class LLViewerOctreeEntryData : public LLRefCount
 	
 	virtual void setOctreeEntry(LLViewerOctreeEntry* entry);
 
-	virtual S32  getMinFrameRange()const = 0;
+	virtual U32  getMinFrameRange()const = 0;
 
 	F32                  getBinRadius() const   {return mEntry->getBinRadius();}
 	const LLVector4a*    getSpatialExtents() const;
diff --git a/indra/newview/llvocache.cpp b/indra/newview/llvocache.cpp
index 68f21ed2b3f639499987b0a8a966e3e8266f3e26..93daf2e1713fbdd316b2cafc4c07f771e279a47a 100755
--- a/indra/newview/llvocache.cpp
+++ b/indra/newview/llvocache.cpp
@@ -50,6 +50,14 @@ BOOL check_write(LLAPRFile* apr_file, void* src, S32 n_bytes)
 //---------------------------------------------------------------------------
 // LLVOCacheEntry
 //---------------------------------------------------------------------------
+//return number of frames invisible objects should stay in memory
+//static 
+U32 LLVOCacheEntry::getInvisibleObjectsLiveTime()
+{
+	static LLCachedControl<U32> inv_obj_time(gSavedSettings,"InvisibleObjectsInMemoryTime");
+
+	return inv_obj_time - 1; //make 0 to be the maximum 
+}
 
 LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &dp)
 	: LLViewerOctreeEntryData(LLViewerOctreeEntry::LLVOCACHEENTRY),
@@ -60,7 +68,6 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &
 	mDupeCount(0),
 	mCRCChangeCount(0),
 	mState(INACTIVE),
-	mMinFrameRange(64),
 	mSceneContrib(0.f),
 	mTouched(TRUE),
 	mParentID(0)
@@ -68,6 +75,7 @@ LLVOCacheEntry::LLVOCacheEntry(U32 local_id, U32 crc, LLDataPackerBinaryBuffer &
 	mBuffer = new U8[dp.getBufferSize()];
 	mDP.assignBuffer(mBuffer, dp.getBufferSize());
 	mDP = dp;
+	mMinFrameRange = getInvisibleObjectsLiveTime();
 }
 
 LLVOCacheEntry::LLVOCacheEntry()
@@ -80,12 +88,12 @@ LLVOCacheEntry::LLVOCacheEntry()
 	mCRCChangeCount(0),
 	mBuffer(NULL),
 	mState(INACTIVE),
-	mMinFrameRange(64),
 	mSceneContrib(0.f),
 	mTouched(TRUE),
 	mParentID(0)
 {
 	mDP.assignBuffer(mBuffer, 0);
+	mMinFrameRange = getInvisibleObjectsLiveTime();
 }
 
 LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
@@ -93,7 +101,6 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 	mBuffer(NULL),
 	mUpdateFlags(-1),
 	mState(INACTIVE),
-	mMinFrameRange(64),
 	mSceneContrib(0.f),
 	mTouched(FALSE),
 	mParentID(0)
@@ -101,6 +108,7 @@ LLVOCacheEntry::LLVOCacheEntry(LLAPRFile* apr_file)
 	S32 size = -1;
 	BOOL success;
 
+	mMinFrameRange = getInvisibleObjectsLiveTime();
 	mDP.assignBuffer(mBuffer, 0);
 	
 	success = check_read(apr_file, &mLocalID, sizeof(U32));
@@ -218,17 +226,17 @@ void LLVOCacheEntry::setState(U32 state)
 
 		if(getVisible() - last_visible < MIN_REAVTIVE_INTERVAL + mMinFrameRange)
 		{
-			mMinFrameRange = llmin(mMinFrameRange * 2, 2048);
+			mMinFrameRange = llmin(mMinFrameRange * 2, getInvisibleObjectsLiveTime() * 32);
 		}
 		else
 		{
-			mMinFrameRange = 64; //reset
+			mMinFrameRange = getInvisibleObjectsLiveTime(); //reset
 		}
 	}
 }
 
 //virtual 
-S32  LLVOCacheEntry::getMinFrameRange()const
+U32  LLVOCacheEntry::getMinFrameRange()const
 {
 	return mMinFrameRange;
 }
diff --git a/indra/newview/llvocache.h b/indra/newview/llvocache.h
index e46fec9dc358ee39ac771ab44bffddf6f9ea7322..b8a7ccac99fb5ea69bff1e13b4bf7205c00fe209 100755
--- a/indra/newview/llvocache.h
+++ b/indra/newview/llvocache.h
@@ -88,7 +88,7 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	U32 getCRC() const				{ return mCRC; }
 	S32 getHitCount() const			{ return mHitCount; }
 	S32 getCRCChangeCount() const	{ return mCRCChangeCount; }
-	S32 getMinFrameRange()const;	
+	U32 getMinFrameRange()const;	
 
 	void calcSceneContribution(const LLVector3& camera_origin, bool needs_update, U32 last_update);
 	void setSceneContribution(F32 scene_contrib) {mSceneContrib = scene_contrib;}
@@ -121,6 +121,9 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	void setUpdateFlags(U32 flags) {mUpdateFlags = flags;}
 	U32  getUpdateFlags() const    {return mUpdateFlags;}
 
+private:
+	static U32  getInvisibleObjectsLiveTime();
+
 public:
 	typedef std::map<U32, LLPointer<LLVOCacheEntry> >	   vocache_entry_map_t;
 	typedef std::set<LLVOCacheEntry*>                      vocache_entry_set_t;
@@ -138,7 +141,7 @@ class LLVOCacheEntry : public LLViewerOctreeEntryData
 	U8							*mBuffer;
 
 	F32                         mSceneContrib; //projected scene contributuion of this object.
-	S32                         mMinFrameRange;
+	U32                         mMinFrameRange;
 	U32                         mState; //high 16 bits reserved for special use.
 	std::vector<LLVOCacheEntry*> mChildrenList; //children entries in a linked set.