SL-19159 Faster LLUUID and LLMaterialID hashing for std and boost containers keys (#70)

LLUUID and LLMaterialID already have an excellent entropy and value dispersion; there is therefore strictly no need to further (slowly) hash their value for use with std and boost libraries containers.

This commit adds a trivial getDigest64() method to both LLUUID and LLMaterialID (which simply returns the XOR of the two 64 bits long words their value is made of), and uses it in std::hash and hash_value() specializations for use with containers.
meow-7.2.2
Henri Beauchamp 2023-02-07 13:51:53 +01:00 committed by GitHub
parent 61b93e778b
commit 1eb2b23f4b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 38 deletions

View File

@ -878,7 +878,7 @@ U32 LLUUID::getRandomSeed()
seed[7]=(unsigned char)(pid);
getSystemTime((uuid_time_t *)(&seed[8]));
U64 seed64 = HBXXH64((const void*)seed, 16).digest();
U64 seed64 = HBXXH64::digest((const void*)seed, 16);
return U32(seed64) ^ U32(seed64 >> 32);
}

View File

@ -119,6 +119,14 @@ public:
U16 getCRC16() const;
U32 getCRC32() const;
// Returns a 64 bits digest of the UUID, by XORing its two 64 bits long
// words. HB
inline U64 getDigest64() const
{
U64* tmp = (U64*)mData;
return tmp[0] ^ tmp[1];
}
static BOOL validate(const std::string& in_string); // Validate that the UUID string is legal.
static const LLUUID null;
@ -165,36 +173,20 @@ public:
LLAssetID makeAssetID(const LLUUID& session) const;
};
// Generate a hash of an LLUUID object using the boost hash templates.
template <>
struct boost::hash<LLUUID>
{
typedef LLUUID argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& s) const
{
result_type seed(0);
for (S32 i = 0; i < UUID_BYTES; ++i)
{
boost::hash_combine(seed, s.mData[i]);
}
return seed;
}
};
// Adapt boost hash to std hash
// std::hash implementation for LLUUID
namespace std
{
template<> struct hash<LLUUID>
{
std::size_t operator()(LLUUID const& s) const noexcept
{
return boost::hash<LLUUID>()(s);
}
};
template<> struct hash<LLUUID>
{
inline size_t operator()(const LLUUID& id) const noexcept
{
return (size_t)id.getDigest64();
}
};
}
#endif
// For use with boost containers.
inline size_t hash_value(const LLUUID& id) noexcept
{
return (size_t)id.getDigest64();
}

View File

@ -66,6 +66,14 @@ public:
static const LLMaterialID null;
// Returns a 64 bits digest of the material Id, by XORing its two 64 bits
// long words. HB
inline U64 getDigest64() const
{
U64* tmp = (U64*)mID;
return tmp[0] ^ tmp[1];
}
private:
void parseFromBinary(const LLSD::Binary& pMaterialID);
void copyFromOtherMaterialID(const LLMaterialID& pOtherMaterialID);
@ -74,5 +82,23 @@ private:
U8 mID[MATERIAL_ID_SIZE];
} ;
// std::hash implementation for LLMaterialID
namespace std
{
template<> struct hash<LLMaterialID>
{
inline size_t operator()(const LLMaterialID& id) const noexcept
{
return (size_t)id.getDigest64();
}
};
}
// For use with boost containers.
inline size_t hash_value(const LLMaterialID& id) noexcept
{
return (size_t)id.getDigest64();
}
#endif // LL_LLMATERIALID_H

View File

@ -102,13 +102,6 @@ private:
(lhs.materialID < rhs.materialID);
}
struct TEMaterialPairHasher
{
enum { bucket_size = 8 };
size_t operator()(const TEMaterialPair& key_value) const { return *((size_t*)key_value.materialID.get()); } // cheesy, but effective
bool operator()(const TEMaterialPair& left, const TEMaterialPair& right) const { return left < right; }
};
typedef std::set<LLMaterialID> material_queue_t;
typedef std::map<LLUUID, material_queue_t> get_queue_t;
typedef std::pair<const LLUUID, LLMaterialID> pending_material_t;
@ -116,7 +109,7 @@ private:
typedef std::map<LLMaterialID, get_callback_t*> get_callback_map_t;
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*, TEMaterialPairHasher> get_callback_te_map_t;
typedef boost::unordered_map<TEMaterialPair, get_callback_te_t*> get_callback_te_map_t;
typedef std::set<LLUUID> getall_queue_t;
typedef std::map<LLUUID, F64> getall_pending_map_t;
typedef std::map<LLUUID, getall_callback_t*> getall_callback_map_t;
@ -146,5 +139,23 @@ private:
U32 getMaxEntries(const LLViewerRegion* regionp);
};
// std::hash implementation for TEMaterialPair
namespace std
{
template<> struct hash<LLMaterialMgr::TEMaterialPair>
{
inline size_t operator()(const LLMaterialMgr::TEMaterialPair& p) const noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
};
}
// For use with boost containers.
inline size_t hash_value(const LLMaterialMgr::TEMaterialPair& p) noexcept
{
return size_t((p.te + 1) * p.materialID.getDigest64());
}
#endif // LL_LLMATERIALMGR_H