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
parent
61b93e778b
commit
1eb2b23f4b
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue