diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d56408939eae108f2def493931065ca128fff87e..896896d7b9423856e85cf8468c38721ea0d61b02 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -102,6 +102,7 @@ const U32 DEFAULT_MAX_REGION_WIDE_PRIM_COUNT = 15000;
 BOOL LLViewerRegion::sVOCacheCullingEnabled = FALSE;
 S32  LLViewerRegion::sLastCameraUpdated = 0;
 S32  LLViewerRegion::sNewObjectCreationThrottle = -1;
+LLViewerRegion::vocache_entry_map_t LLViewerRegion::sRegionCacheCleanup;
 
 typedef std::map<std::string, std::string> CapabilityMap;
 
@@ -635,6 +636,9 @@ void LLViewerRegion::initStats()
 	mAlive = false;					// can become false if circuit disconnects
 }
 
+static LLTrace::BlockTimerStatHandle FTM_CLEANUP_REGION_OBJECTS("Cleanup Region Objects");
+static LLTrace::BlockTimerStatHandle FTM_SAVE_REGION_CACHE("Save Region Cache");
+
 LLViewerRegion::~LLViewerRegion() 
 {
 	mDead = TRUE;
@@ -649,7 +653,10 @@ LLViewerRegion::~LLViewerRegion()
 	disconnectAllNeighbors();
 	LLViewerPartSim::getInstance()->cleanupRegion(this);
 
-	gObjectList.killObjects(this);
+    {
+        LL_RECORD_BLOCK_TIME(FTM_CLEANUP_REGION_OBJECTS);
+        gObjectList.killObjects(this);
+    }
 
 	delete mImpl->mCompositionp;
 	delete mParcelOverlay;
@@ -660,7 +667,10 @@ LLViewerRegion::~LLViewerRegion()
 #endif	
 	std::for_each(mImpl->mObjectPartition.begin(), mImpl->mObjectPartition.end(), DeletePointer());
 
-	saveObjectCache();
+    {
+        LL_RECORD_BLOCK_TIME(FTM_SAVE_REGION_CACHE);
+        saveObjectCache();
+    }
 
 	delete mImpl;
 	mImpl = NULL;
@@ -729,6 +739,8 @@ void LLViewerRegion::saveObjectCache()
 		mCacheDirty = FALSE;
 	}
 
+	// Map of LLVOCacheEntry takes time to release, store map for cleanup on idle
+	sRegionCacheCleanup.insert(mImpl->mCacheMap.begin(), mImpl->mCacheMap.end());
 	mImpl->mCacheMap.clear();
 }
 
@@ -1490,6 +1502,16 @@ void LLViewerRegion::idleUpdate(F32 max_update_time)
 	return;
 }
 
+// static
+void LLViewerRegion::idleCleanup(F32 max_update_time)
+{
+    LLTimer update_timer;
+    while (!sRegionCacheCleanup.empty() && (max_update_time - update_timer.getElapsedTimeF32() > 0))
+    {
+        sRegionCacheCleanup.erase(sRegionCacheCleanup.begin());
+    }
+}
+
 //update the throttling number for new object creation
 void LLViewerRegion::calcNewObjectCreationThrottle()
 {
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index f7c50e4de5860caedf3db3c429be112c6582f736..477aabb971f5d82d938c6784546300e6ffc51756 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -232,6 +232,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	F32	getWidth() const						{ return mWidth; }
 
+	// regions are expensive to release, this function gradually releases cache from memory
+	static void idleCleanup(F32 max_update_time);
+
 	void idleUpdate(F32 max_update_time);
 	void lightIdleUpdate();
 	bool addVisibleGroup(LLViewerOctreeGroup* group);
@@ -550,6 +553,9 @@ class LLViewerRegion: public LLCapabilityProvider // implements this interface
 
 	LLSD mSimulatorFeatures;
 
+    typedef std::map<U32, LLPointer<LLVOCacheEntry> >	   vocache_entry_map_t;
+    static vocache_entry_map_t sRegionCacheCleanup;
+
 	// the materials capability throttle
 	LLFrameTimer mMaterialsCapThrottleTimer;
 	LLFrameTimer mRenderInfoRequestTimer;
diff --git a/indra/newview/llworld.cpp b/indra/newview/llworld.cpp
index 8989bae96a7fd5ed8329ca5b9ef04c8e99219bc8..c5dd274c33ce402b729d079206da7efffad496f1 100644
--- a/indra/newview/llworld.cpp
+++ b/indra/newview/llworld.cpp
@@ -730,11 +730,20 @@ void LLWorld::updateRegions(F32 max_update_time)
 		{
 			//perform some necessary but very light updates.
 			(*iter)->lightIdleUpdate();
-		}		
+		}
+	}
+
+	if(max_time > 0.f)
+	{
+		max_time = llmin((F32)(max_update_time - update_timer.getElapsedTimeF32()), max_update_time * 0.25f);
+	}
+	if(max_time > 0.f)
+	{
+		LLViewerRegion::idleCleanup(max_time);
 	}
 
 	sample(sNumActiveCachedObjects, mNumOfActiveCachedObjects);
-		}
+}
 
 void LLWorld::clearAllVisibleObjects()
 {
@@ -1208,11 +1217,12 @@ class LLEstablishAgentCommunication : public LLHTTPNode
 	}
 };
 
+static LLTrace::BlockTimerStatHandle FTM_DISABLE_REGION("Disable Region");
 // disable the circuit to this simulator
 // Called in response to "DisableSimulator" message.
 void process_disable_simulator(LLMessageSystem *mesgsys, void **user_data)
-{	
-	LLHost host = mesgsys->getSender();
+{
+    LL_RECORD_BLOCK_TIME(FTM_DISABLE_REGION);	LLHost host = mesgsys->getSender();
 
 	//LL_INFOS() << "Disabling simulator with message from " << host << LL_ENDL;
 	LLWorld::getInstance()->removeRegion(host);