Scott Lawrence avatar Scott Lawrence committed dbaaef1 Merge

merge changes for vwr-26864

Comments (0)

Files changed (5)

indra/llcommon/llmemory.cpp

 	llinfos << "Current allocated page size (KB): " << sAllocatedPageSizeInKB << llendl ;
 	llinfos << "Current availabe physical memory(KB): " << sAvailPhysicalMemInKB << llendl ;
 	llinfos << "Current max usable memory(KB): " << sMaxPhysicalMemInKB << llendl ;
+
+	llinfos << "--- private pool information -- " << llendl ;
+	llinfos << "Total reserved (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalReservedSize / 1024 << llendl ;
+	llinfos << "Total allocated (KB): " << LLPrivateMemoryPoolManager::getInstance()->mTotalAllocatedSize / 1024 << llendl ;
 }
 
 //return 0: everything is normal;
 //return 1: the memory pool is low, but not in danger;
 //return -1: the memory pool is in danger, is about to crash.
 //static 
-S32 LLMemory::isMemoryPoolLow()
+bool LLMemory::isMemoryPoolLow()
 {
 	static const U32 LOW_MEMEOY_POOL_THRESHOLD_KB = 64 * 1024 ; //64 MB for emergency use
+	const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
+	static void* last_reserved_address = NULL ;
 
 	if(!sEnableMemoryFailurePrevention)
 	{
-		return 0 ; //no memory failure prevention.
+		return false ; //no memory failure prevention.
 	}
 
 	if(sAvailPhysicalMemInKB < (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2)) //out of physical memory
 	{
-		return -1 ;
+		return true ;
 	}
 
 	if(sAllocatedPageSizeInKB + (LOW_MEMEOY_POOL_THRESHOLD_KB >> 2) > sMaxHeapSizeInKB) //out of virtual address space.
 	{
-		return -1 ;
+		return true ;
 	}
 
-	return (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || 
+	bool is_low = (S32)(sAvailPhysicalMemInKB < LOW_MEMEOY_POOL_THRESHOLD_KB || 
 		sAllocatedPageSizeInKB + LOW_MEMEOY_POOL_THRESHOLD_KB > sMaxHeapSizeInKB) ;
+
+	//check the virtual address space fragmentation
+	if(!is_low)
+	{
+		if(!last_reserved_address)
+		{
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+		}
+		else
+		{
+			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			if(!last_reserved_address) //failed, try once more
+			{
+				last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
+			}
+		}
+
+		is_low = !last_reserved_address ; //allocation failed
+	}
+
+	return is_low ;
 }
 
 //static 
 //--------------------------------------------------------------------
 const U32 CHUNK_SIZE = 4 << 20 ; //4 MB
 const U32 LARGE_CHUNK_SIZE = 4 * CHUNK_SIZE ; //16 MB
-LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type) :
+LLPrivateMemoryPool::LLPrivateMemoryPool(S32 type, U32 max_pool_size) :
 	mMutexp(NULL),	
 	mReservedPoolSize(0),
 	mHashFactor(1),
-	mType(type)
+	mType(type),
+	mMaxPoolSize(max_pool_size)
 {
-	const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB
-
-	mMaxPoolSize = MAX_POOL_SIZE ;
 	if(type == STATIC_THREADED || type == VOLATILE_THREADED)
 	{
 		mMutexp = new LLMutex ;
 				chunk = chunk->mNext ;
 			}
 		}
-
-		chunk = addChunk(chunk_idx) ;
-		if(chunk)
+		else
 		{
-			p = chunk->allocate(size) ;
+			chunk = addChunk(chunk_idx) ;
+			if(chunk)
+			{
+				p = chunk->allocate(size) ;
+			}
 		}
 	}
 
 	unlock() ;
 
+	if(!p) //to get memory from the private pool failed, try the heap directly
+	{
+		static bool to_log = true ;
+		
+		if(to_log)
+		{
+			llwarns << "The memory pool overflows, now using heap directly!" << llendl ;
+			to_log = false ;
+		}
+
+		return (char*)malloc(size) ;
+	}
+
 	return p ;
 }
 
 	unlock() ;
 }
 
-void  LLPrivateMemoryPool::checkSize(U32 asked_size)
+bool LLPrivateMemoryPool::checkSize(U32 asked_size)
 {
 	if(mReservedPoolSize + asked_size > mMaxPoolSize)
 	{
 		llinfos << "Total reserved size: " << mReservedPoolSize + asked_size << llendl ;
 		llinfos << "Total_allocated Size: " << getTotalAllocatedSize() << llendl ;
 
-		llerrs << "The pool is overflowing..." << llendl ;
+		//llerrs << "The pool is overflowing..." << llendl ;
+
+		return false ;
 	}
+
+	return true ;
 }
 
 LLPrivateMemoryPool::LLMemoryChunk* LLPrivateMemoryPool::addChunk(S32 chunk_index)
 			MAX_SLOT_SIZES[chunk_index], MIN_BLOCK_SIZES[chunk_index], MAX_BLOCK_SIZES[chunk_index]) ;
 	}
 
-	checkSize(preferred_size + overhead) ;
+	if(!checkSize(preferred_size + overhead))
+	{
+		return NULL ;
+	}
+
 	mReservedPoolSize += preferred_size + overhead ;
 
 	char* buffer = (char*)malloc(preferred_size + overhead) ;
 
 void LLPrivateMemoryPool::addToHashTable(LLMemoryChunk* chunk) 
 {
-	static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 0xFFFF}; 
+	static const U16 HASH_FACTORS[] = {41, 83, 193, 317, 419, 523, 719, 997, 1523, 0xFFFF}; 
 	
 	U16 i ;
 	if(mChunkHashList.empty())
 //--------------------------------------------------------------------
 LLPrivateMemoryPoolManager* LLPrivateMemoryPoolManager::sInstance = NULL ;
 
-LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled) 
+LLPrivateMemoryPoolManager::LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) 
 {
 	mPoolList.resize(LLPrivateMemoryPool::MAX_TYPES) ;
 
 	}
 
 	mPrivatePoolEnabled = enabled ;
+
+	const U32 MAX_POOL_SIZE = 256 * 1024 * 1024 ; //256 MB
+	mMaxPrivatePoolSize = llmax(max_pool_size, MAX_POOL_SIZE) ;
 }
 
 LLPrivateMemoryPoolManager::~LLPrivateMemoryPoolManager() 
 }
 
 //static 
-void LLPrivateMemoryPoolManager::initClass(BOOL enabled) 
+void LLPrivateMemoryPoolManager::initClass(BOOL enabled, U32 max_pool_size) 
 {
 	llassert_always(!sInstance) ;
 
-	sInstance = new LLPrivateMemoryPoolManager(enabled) ;
+	sInstance = new LLPrivateMemoryPoolManager(enabled, max_pool_size) ;
 }
 
 //static 
 
 	if(!mPoolList[type])
 	{
-		mPoolList[type] = new LLPrivateMemoryPool(type) ;
+		mPoolList[type] = new LLPrivateMemoryPool(type, mMaxPrivatePoolSize) ;
 	}
 
 	return mPoolList[type] ;

indra/llcommon/llmemory.h

 	static void initMaxHeapSizeGB(F32 max_heap_size_gb, BOOL prevent_heap_failure);
 	static void updateMemoryInfo() ;
 	static void logMemoryInfo(BOOL update = FALSE);
-	static S32  isMemoryPoolLow();
+	static bool isMemoryPoolLow();
 
 	static U32 getAvailableMemKB() ;
 	static U32 getMaxMemKB() ;
 	} ;
 
 private:
-	LLPrivateMemoryPool(S32 type) ;
+	LLPrivateMemoryPool(S32 type, U32 max_pool_size) ;
 	~LLPrivateMemoryPool() ;
 
 	char *allocate(U32 size) ;
 	void unlock() ;	
 	S32 getChunkIndex(U32 size) ;
 	LLMemoryChunk*  addChunk(S32 chunk_index) ;
-	void checkSize(U32 asked_size) ;
+	bool checkSize(U32 asked_size) ;
 	void removeChunk(LLMemoryChunk* chunk) ;
 	U16  findHashKey(const char* addr);
 	void addToHashTable(LLMemoryChunk* chunk) ;
 class LL_COMMON_API LLPrivateMemoryPoolManager
 {
 private:
-	LLPrivateMemoryPoolManager(BOOL enabled) ;
+	LLPrivateMemoryPoolManager(BOOL enabled, U32 max_pool_size) ;
 	~LLPrivateMemoryPoolManager() ;
 
 public:	
 	static LLPrivateMemoryPoolManager* getInstance() ;
-	static void initClass(BOOL enabled) ;
+	static void initClass(BOOL enabled, U32 pool_size) ;
 	static void destroyClass() ;
 
 	LLPrivateMemoryPool* newPool(S32 type) ;
 	static LLPrivateMemoryPoolManager* sInstance ;
 	std::vector<LLPrivateMemoryPool*> mPoolList ;
 	BOOL mPrivatePoolEnabled;
+	U32  mMaxPrivatePoolSize;
 
 public:
 	//debug and statistics info.

indra/newview/app_settings/settings.xml

       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>MemoryPrivatePoolSize</key>
+    <map>
+      <key>Comment</key>
+      <string>Size of the private memory pool in MB (min. value is 256)</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>U32</string>
+      <key>Value</key>
+      <integer>512</integer>
+    </map>
     <key>MemProfiling</key>
     <map>
       <key>Comment</key>

indra/newview/llappviewer.cpp

 	//set the max heap size.
 	initMaxHeapSize() ;
 
-	LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled")) ;
+	LLPrivateMemoryPoolManager::initClass((BOOL)gSavedSettings.getBOOL("MemoryPrivatePoolEnabled"), (U32)gSavedSettings.getU32("MemoryPrivatePoolSize")) ;
 
 	// write Google Breakpad minidump files to our log directory
 	std::string logdir = gDirUtilp->getExpandedFilename(LL_PATH_LOGS, "");
 {
 	const static F32 MEMORY_CHECK_INTERVAL = 1.0f ; //second
 	//const static F32 MAX_QUIT_WAIT_TIME = 30.0f ; //seconds
-	const static U32 MAX_SIZE_CHECKED_MEMORY_BLOCK = 64 * 1024 * 1024 ; //64 MB
-	//static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
-	static void* last_reserved_address = NULL ;
+	//static F32 force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;	
+
+	if(!gGLManager.mDebugGPU)
+	{
+		return ;
+	}
 
 	if(MEMORY_CHECK_INTERVAL > mMemCheckTimer.getElapsedTimeF32())
 	{
 	}
 	mMemCheckTimer.reset() ;
 
-	if(gGLManager.mDebugGPU)
-	{
-		//update the availability of memory
-		LLMemory::updateMemoryInfo() ;
-	}
-
-	//check the virtual address space fragmentation
-	if(!last_reserved_address)
-	{
-		last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
-	}
-	else
-	{
-		last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
-		if(!last_reserved_address) //failed, try once more
-		{
-			last_reserved_address = LLMemory::tryToAlloc(last_reserved_address, MAX_SIZE_CHECKED_MEMORY_BLOCK) ;
-		}
-	}
-
-	S32 is_low = !last_reserved_address || LLMemory::isMemoryPoolLow() ;
-
-	//if(is_low < 0) //to force quit
-	//{
-	//	if(force_quit_timer > MAX_QUIT_WAIT_TIME) //just hit the limit for the first time
-	//	{
-	//		//send out the notification to tell the viewer is about to quit in 30 seconds.
-	//		LLNotification::Params params("ForceQuitDueToLowMemory");
-	//		LLNotifications::instance().add(params);
-
-	//		force_quit_timer = MAX_QUIT_WAIT_TIME - MEMORY_CHECK_INTERVAL ;
-	//	}
-	//	else
-	//	{
-	//		force_quit_timer -= MEMORY_CHECK_INTERVAL ;
-	//		if(force_quit_timer < 0.f)
-	//		{
-	//			forceQuit() ; //quit
-	//		}
-	//	}
-	//}
-	//else
-	//{
-	//	force_quit_timer = MAX_QUIT_WAIT_TIME + MEMORY_CHECK_INTERVAL ;
-	//}
-
-	LLPipeline::throttleNewMemoryAllocation(!is_low ? FALSE : TRUE) ;		
+	//update the availability of memory
+	LLMemory::updateMemoryInfo() ;
+
+	bool is_low = LLMemory::isMemoryPoolLow() ;
+
+	LLPipeline::throttleNewMemoryAllocation(is_low) ;		
 	
 	if(is_low)
 	{

indra/newview/llviewerdisplay.cpp

 		gMemoryAllocated = LLMemory::getCurrentRSS();
 		U32 memory = (U32)(gMemoryAllocated / (1024*1024));
 		llinfos << llformat("MEMORY: %d MB", memory) << llendl;
-		LLMemory::logMemoryInfo() ;
+		LLMemory::logMemoryInfo(TRUE) ;
 		gRecentMemoryTime.reset();
 	}
 }
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.