summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-01-30 23:02:53 +0200
committerAndrey Kleshchev <andreykproductengine@lindenlab.com>2025-01-31 03:41:04 +0200
commite97976831d883d9c8ff40a0442a5905ac05dd45a (patch)
treed28f7c98f6a077b3b96f209b1411eb6f511b348b /indra
parentc405cd379a736722740ac241d36bcffb88c236c2 (diff)
#3488 Minimize allocations
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/llmeshrepository.cpp98
-rw-r--r--indra/newview/llmeshrepository.h5
2 files changed, 48 insertions, 55 deletions
diff --git a/indra/newview/llmeshrepository.cpp b/indra/newview/llmeshrepository.cpp
index 2969b42ca5..821288429d 100644
--- a/indra/newview/llmeshrepository.cpp
+++ b/indra/newview/llmeshrepository.cpp
@@ -895,6 +895,8 @@ LLMeshRepoThread::~LLMeshRepoThread()
mHeaderMutex = NULL;
delete mSignal;
mSignal = NULL;
+ delete[] mDiskCacheBuffer;
+ mDiskCacheBuffer = NULL;
}
void LLMeshRepoThread::run()
@@ -1275,6 +1277,41 @@ void LLMeshRepoThread::loadMeshLOD(const LLUUID& mesh_id, const LLVolumeParams&
}
}
+U8* LLMeshRepoThread::getDiskCacheBuffer(S32 size)
+{
+ if (mDiskCacheBufferSize < size)
+ {
+ const S32 MINIMUM_BUFFER_SIZE = 8192; // a minimum to avoid frequent early reallocations
+ size = llmax(MINIMUM_BUFFER_SIZE, size);
+ delete[] mDiskCacheBuffer;
+ try
+ {
+ mDiskCacheBuffer = new U8[size];
+ }
+ catch (std::bad_alloc&)
+ {
+ LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh thread's buffer, size: " << size << LL_ENDL;
+ mDiskCacheBuffer = NULL;
+
+ // Not sure what size is reasonable
+ // but if 30MB allocation failed, we definetely have issues
+ const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
+ if (size < MAX_SIZE)
+ {
+ LLAppViewer::instance()->outOfMemorySoftQuit();
+ } // else ignore failures for anomalously large data
+ }
+ mDiskCacheBufferSize = size;
+ }
+ else
+ {
+ // reusing old buffer, reset heading bytes to ensure
+ // old content won't be parsable if something fails.
+ memset(mDiskCacheBuffer, 0, 16);
+ }
+ return mDiskCacheBuffer;
+}
+
// Mutex: must be holding mMutex when called
void LLMeshRepoThread::setGetMeshCap(const std::string & mesh_cap)
{
@@ -1411,19 +1448,9 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
LLFileSystem file(mesh_id, LLAssetType::AT_MESH);
if (in_cache && file.getSize() >= disk_ofset + size)
{
- U8* buffer = new(std::nothrow) U8[size];
+ U8* buffer = getDiskCacheBuffer(size);
if (!buffer)
{
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for skin info, size: " << size << LL_ENDL;
-
- // Not sure what size is reasonable for skin info,
- // but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
- if (size < MAX_SIZE)
- {
- LLAppViewer::instance()->outOfMemorySoftQuit();
- } // else ignore failures for anomalously large data
- LLMutexLock locker(mMutex);
mSkinUnavailableQ.emplace_back(mesh_id);
return true;
}
@@ -1443,12 +1470,9 @@ bool LLMeshRepoThread::fetchMeshSkinInfo(const LLUUID& mesh_id, bool can_retry)
{ //attempt to parse
if (skinInfoReceived(mesh_id, buffer, size))
{
- delete[] buffer;
return true;
}
}
-
- delete[] buffer;
}
//reading from cache failed for whatever reason, fetch from sim
@@ -1537,18 +1561,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
LLFileSystem file(mesh_id, LLAssetType::AT_MESH);
if (in_cache && file.getSize() >= disk_ofset + size)
{
- U8* buffer = new(std::nothrow) U8[size];
+ U8* buffer = getDiskCacheBuffer(size);
if (!buffer)
{
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
-
- // Not sure what size is reasonable for decomposition
- // but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
- if (size < MAX_SIZE)
- {
- LLAppViewer::instance()->outOfMemorySoftQuit();
- } // else ignore failures for anomalously large decompositiions
return true;
}
LLMeshRepository::sCacheBytesRead += size;
@@ -1568,12 +1583,9 @@ bool LLMeshRepoThread::fetchMeshDecomposition(const LLUUID& mesh_id)
{ //attempt to parse
if (decompositionReceived(mesh_id, buffer, size))
{
- delete[] buffer;
return true;
}
}
-
- delete[] buffer;
}
//reading from cache failed for whatever reason, fetch from sim
@@ -1650,21 +1662,13 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
{
LLMeshRepository::sCacheBytesRead += size;
++LLMeshRepository::sCacheReads;
- file.seek(disk_ofset);
- U8* buffer = new(std::nothrow) U8[size];
+
+ U8* buffer = getDiskCacheBuffer(size);
if (!buffer)
{
- LL_WARNS(LOG_MESH) << "Failed to allocate memory for mesh decomposition, size: " << size << LL_ENDL;
-
- // Not sure what size is reasonable for physcis
- // but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
- if (size < MAX_SIZE)
- {
- LLAppViewer::instance()->outOfMemorySoftQuit();
- } // else ignore failures for anomalously large data
return true;
}
+ file.seek(disk_ofset);
file.read(buffer, size);
//make sure buffer isn't all 0's by checking the first 1KB (reserved block but not written)
@@ -1678,12 +1682,9 @@ bool LLMeshRepoThread::fetchMeshPhysicsShape(const LLUUID& mesh_id)
{ //attempt to parse
if (physicsShapeReceived(mesh_id, buffer, size) == MESH_OK)
{
- delete[] buffer;
return true;
}
}
-
- delete[] buffer;
}
//reading from cache failed for whatever reason, fetch from sim
@@ -1885,18 +1886,9 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
LLFileSystem file(mesh_id, LLAssetType::AT_MESH);
if (in_cache && file.getSize() >= disk_ofset + size)
{
- U8* buffer = new(std::nothrow) U8[size];
+ U8* buffer = getDiskCacheBuffer(size);
if (!buffer)
{
- LL_WARNS(LOG_MESH) << "Can't allocate memory for mesh " << mesh_id << " LOD " << lod << ", size: " << size << LL_ENDL;
-
- // Not sure what size is reasonable for a mesh,
- // but if 20MB allocation failed, we definetely have issues
- const S32 MAX_SIZE = 30 * 1024 * 1024; //30MB
- if (size < MAX_SIZE)
- {
- LLAppViewer::instance()->outOfMemorySoftQuit();
- } // else ignore failures for anomalously large data
LLMutexLock lock(mMutex);
mUnavailableQ.push_back(LODRequest(mesh_params, lod));
return true;
@@ -1917,15 +1909,11 @@ bool LLMeshRepoThread::fetchMeshLOD(const LLVolumeParams& mesh_params, S32 lod,
{ //attempt to parse
if (lodReceived(mesh_params, lod, buffer, size) == MESH_OK)
{
- delete[] buffer;
-
LL_DEBUGS(LOG_MESH) << "Mesh/Cache: Mesh body for ID " << mesh_id << " - was retrieved from the cache." << LL_ENDL;
return true;
}
}
-
- delete[] buffer;
}
//reading from cache failed for whatever reason, fetch from sim
diff --git a/indra/newview/llmeshrepository.h b/indra/newview/llmeshrepository.h
index d11ea581cd..2e29daf9ec 100644
--- a/indra/newview/llmeshrepository.h
+++ b/indra/newview/llmeshrepository.h
@@ -576,6 +576,11 @@ private:
// Mutex: mMutex must be alerady locked when calling
void loadMeshLOD(const LLUUID &mesh_id, const LLVolumeParams& mesh_params, S32 lod);
+
+ // Threads: Repo thread only
+ U8* getDiskCacheBuffer(S32 size);
+ S32 mDiskCacheBufferSize = 0;
+ U8* mDiskCacheBuffer = nullptr;
};