From c47c1fdd096ddf8c0427f3c7328d958d95e67649 Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@bred.dog>
Date: Sat, 10 Aug 2019 16:31:23 -0400
Subject: [PATCH] Optimize findImage with a hashmap find

---
 indra/newview/llviewertexturelist.cpp | 28 +++++++++++++++------------
 indra/newview/llviewertexturelist.h   | 17 +++++++++++++++-
 2 files changed, 32 insertions(+), 13 deletions(-)

diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index c0c891fab6..c464b2934c 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -119,6 +119,7 @@ void LLViewerTextureList::doPreloadImages()
 	llassert_always(mInitialized) ;
 	llassert_always(mImageList.empty()) ;
 	llassert_always(mUUIDMap.empty()) ;
+	llassert_always(mUUIDHashMap.empty());
 
 	// Set the "missing asset" image
 	LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", FTT_LOCAL_FILE, MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
@@ -326,6 +327,7 @@ void LLViewerTextureList::shutdown()
 	mFastCacheList.clear();
 	
 	mUUIDMap.clear();
+	mUUIDHashMap.clear();
 	
 	mImageList.clear();
 
@@ -622,8 +624,8 @@ void LLViewerTextureList::findTexturesByID(const LLUUID &image_id, std::vector<L
 
 LLViewerFetchedTexture *LLViewerTextureList::findImage(const LLTextureKey &search_key)
 {
-    uuid_map_t::iterator iter = mUUIDMap.find(search_key);
-    if (iter == mUUIDMap.end())
+    const auto& iter = mUUIDHashMap.find(search_key);
+    if (iter == mUUIDHashMap.cend())
         return NULL;
     return iter->second;
 }
@@ -644,12 +646,12 @@ void LLViewerTextureList::addImageToList(LLViewerFetchedTexture *image)
 	}
 	else
 	{
-	if((mImageList.insert(image)).second != true) 
-	{
-			LL_WARNS() << "Error happens when insert image " << image->getID()  << " into mImageList!" << LL_ENDL ;
+		if((mImageList.insert(image)).second != true) 
+		{
+				LL_WARNS() << "Error happens when insert image " << image->getID()  << " into mImageList!" << LL_ENDL ;
+		}
+		image->setInImageList(TRUE) ;
 	}
-	image->setInImageList(TRUE) ;
-}
 }
 
 void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
@@ -675,17 +677,17 @@ void LLViewerTextureList::removeImageFromList(LLViewerFetchedTexture *image)
 			<< " but doesn't have mInImageList set"
 			<< " ref count is " << image->getNumRefs()
 			<< LL_ENDL;
-		uuid_map_t::iterator iter = mUUIDMap.find(LLTextureKey(image->getID(), (ETexListType)image->getTextureListType()));
-		if(iter == mUUIDMap.end())
+		const auto& iter = mUUIDHashMap.find(LLTextureKey(image->getID(), (ETexListType)image->getTextureListType()));
+		if(iter == mUUIDHashMap.cend())
 		{
 			LL_INFOS() << "Image  " << image->getID() << " is also not in mUUIDMap!" << LL_ENDL ;
 		}
 		else if (iter->second != image)
 		{
 			LL_INFOS() << "Image  " << image->getID() << " was in mUUIDMap but with different pointer" << LL_ENDL ;
-	}
+		}
 		else
-	{
+		{
 			LL_INFOS() << "Image  " << image->getID() << " was in mUUIDMap with same pointer" << LL_ENDL ;
 		}
 		count = mImageList.erase(image) ;
@@ -718,7 +720,8 @@ void LLViewerTextureList::addImage(LLViewerFetchedTexture *new_image, ETexListTy
 	sNumImages++;
 
 	addImageToList(new_image);
-	mUUIDMap[key] = new_image;
+	mUUIDMap.emplace(key, new_image);
+	mUUIDHashMap.emplace(key, new_image);
 	new_image->setTextureListType(tex_type);
 }
 
@@ -733,6 +736,7 @@ void LLViewerTextureList::deleteImage(LLViewerFetchedTexture *image)
 		}
 		LLTextureKey key(image->getID(), (ETexListType)image->getTextureListType());
 		llverify(mUUIDMap.erase(key) == 1);
+		llverify(mUUIDHashMap.erase(key) == 1);
 		sNumImages--;
 		removeImageFromList(image);
 	}
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index de2dd93930..58880904a0 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -35,6 +35,8 @@
 #include <list>
 #include "lluiimage.h"
 
+#include "absl/container/flat_hash_map.h"
+
 const U32 LL_IMAGE_REZ_LOSSLESS_CUTOFF = 128;
 
 const BOOL MIPMAP_YES = TRUE;
@@ -82,6 +84,17 @@ struct LLTextureKey
             return key1.textureType < key2.textureType;
         }
     }
+
+	friend bool operator==(const LLTextureKey& lhs, const LLTextureKey& rhs)
+	{
+		return lhs.textureId == rhs.textureId && lhs.textureType == rhs.textureType;
+	}
+
+	template <typename H>
+	friend H AbslHashValue(H h, const LLTextureKey& id) 
+	{
+		return H::combine(std::move(h), id.textureId, id.textureType);
+	}
 };
 
 class LLViewerTextureList
@@ -209,8 +222,10 @@ public:
 	BOOL mForceResetTextureStats;
     
 private:
-    typedef std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> > uuid_map_t;
+    using uuid_map_t = std::map< LLTextureKey, LLPointer<LLViewerFetchedTexture> >;
+	using uuid_hash_map_t = absl::flat_hash_map< LLTextureKey, LLPointer<LLViewerFetchedTexture> >;
     uuid_map_t mUUIDMap;
+	uuid_hash_map_t mUUIDHashMap;
     LLTextureKey mLastUpdateKey;
     LLTextureKey mLastFetchKey;
 	
-- 
GitLab