Commit a9d74b51 authored by danakj@chromium.org's avatar danakj@chromium.org
Browse files

Minimize collisions when hashing pairs

https://bugs.webkit.org/show_bug.cgi?id=96022

Reviewed by Adrienne Walker.

Source/WebCore:

Use WTF::pairIntHash() to hash pairs of integers.

* dom/Document.cpp:
(WebCore::ImmutableAttributeDataCacheKey::hash):
* dom/StyledElement.cpp:
(WebCore::computePresentationAttributeCacheHash):
* platform/graphics/Gradient.cpp:
(WebCore::Gradient::hash):
* platform/graphics/IntPointHash.h:
(WTF::IntPointHash::hash):
* platform/graphics/IntRectHash.h:
* platform/graphics/IntSizeHash.h:
* platform/graphics/blackberry/LayerTileIndex.h:
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::SubimageCacheHash::hash):

Source/WebKit/blackberry:

Use WTF::pairIntHash() to hash a pair of integers.

* WebKitSupport/TileIndexHash.h:

Source/WTF:

The current hash function for pairs has poor performance as it does a
nice hash function on 64 bits, but then just drops the top 32 bits. The
hash method for pairs tries to use Thomas Wang's 64 bit Mix Function,
but this requires not dropping any bits in order to retain the
characteristics mentioned by Thomas.

A better method of hashing sets of 32-bit integers is to use
multiplication in 64 bits with random integers. This method is a
provably almost-universal hash function. Testing shows that this
method decreases the time required, when compared with the current
method, by more than 20% due to better hashing characteristics.

* wtf/HashFunctions.h:
(WTF):
(WTF::pairIntHash):
Implments the hashing method for a pair of unsigned integers.

(WTF::PairHash::hash):
Use pairIntHash() on the hash results of each object in the pair.

(WTF::IntPairHash::hash):
Implement an integer-specific PairHash class that does not need to
hash each object in the pair. It uses pairIntHash on the two
integers in the pair directly.

(WTF::IntPairHash::equal):
(IntPairHash):


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@128650 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent e688af02
2012-09-14 Dana Jansens <danakj@chromium.org>
Minimize collisions when hashing pairs
https://bugs.webkit.org/show_bug.cgi?id=96022
Reviewed by Adrienne Walker.
The current hash function for pairs has poor performance as it does a
nice hash function on 64 bits, but then just drops the top 32 bits. The
hash method for pairs tries to use Thomas Wang's 64 bit Mix Function,
but this requires not dropping any bits in order to retain the
characteristics mentioned by Thomas.
A better method of hashing sets of 32-bit integers is to use
multiplication in 64 bits with random integers. This method is a
provably almost-universal hash function. Testing shows that this
method decreases the time required, when compared with the current
method, by more than 20% due to better hashing characteristics.
* wtf/HashFunctions.h:
(WTF):
(WTF::pairIntHash):
Implments the hashing method for a pair of unsigned integers.
(WTF::PairHash::hash):
Use pairIntHash() on the hash results of each object in the pair.
(WTF::IntPairHash::hash):
Implement an integer-specific PairHash class that does not need to
hash each object in the pair. It uses pairIntHash on the two
integers in the pair directly.
(WTF::IntPairHash::equal):
(IntPairHash):
2012-09-14 Tor Arne Vestbø <tor.arne.vestbo@nokia.com>
[Qt] Make force_static_libs_as_shared work on Mac OS
......
......@@ -86,6 +86,18 @@ namespace WTF {
return static_cast<unsigned>(key);
}
// Compound integer hash method: http://opendatastructures.org/versions/edition-0.1d/ods-java/node33.html#SECTION00832000000000000000
inline unsigned pairIntHash(unsigned key1, unsigned key2)
{
unsigned shortRandom1 = 277951225; // A random 32-bit value.
unsigned shortRandom2 = 95187966; // A random 32-bit value.
uint64_t longRandom = 19248658165952622LL; // A random 64-bit value.
uint64_t product = longRandom * (shortRandom1 * key1 + shortRandom2 * key2);
unsigned highBits = product >> (sizeof(uint64_t) - sizeof(unsigned));
return highBits;
}
template<typename T> struct IntHash {
static unsigned hash(T key) { return intHash(static_cast<typename IntTypes<sizeof(T)>::UnsignedType>(key)); }
static bool equal(T a, T b) { return a == b; }
......@@ -139,7 +151,7 @@ namespace WTF {
template<typename T, typename U> struct PairHash {
static unsigned hash(const std::pair<T, U>& p)
{
return intHash((static_cast<uint64_t>(DefaultHash<T>::Hash::hash(p.first)) << 32 | DefaultHash<U>::Hash::hash(p.second)));
return pairIntHash(DefaultHash<T>::Hash::hash(p.first), DefaultHash<U>::Hash::hash(p.second));
}
static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b)
{
......@@ -149,6 +161,12 @@ namespace WTF {
&& DefaultHash<U>::Hash::safeToCompareToEmptyOrDeleted;
};
template<typename T, typename U> struct IntPairHash {
static unsigned hash(const std::pair<T, U>& p) { return pairIntHash(p.first, p.second); }
static bool equal(const std::pair<T, U>& a, const std::pair<T, U>& b) { return PairHash<T, T>::equal(a, b); }
static const bool safeToCompareToEmptyOrDeleted = PairHash<T, U>::safeToCompareToEmptyOrDeleted;
};
// make IntHash the default hash function for many integer types
template<> struct DefaultHash<short> { typedef IntHash<unsigned> Hash; };
......@@ -172,6 +190,27 @@ namespace WTF {
template<typename P> struct DefaultHash<P*> { typedef PtrHash<P*> Hash; };
template<typename P> struct DefaultHash<RefPtr<P> > { typedef PtrHash<RefPtr<P> > Hash; };
// make IntPairHash the default hash function for pairs of (at most) 32-bit integers.
template<> struct DefaultHash<std::pair<short, short> > { typedef IntPairHash<short, short> Hash; };
template<> struct DefaultHash<std::pair<short, unsigned short> > { typedef IntPairHash<short, unsigned short> Hash; };
template<> struct DefaultHash<std::pair<short, int> > { typedef IntPairHash<short, int> Hash; };
template<> struct DefaultHash<std::pair<short, unsigned> > { typedef IntPairHash<short, unsigned> Hash; };
template<> struct DefaultHash<std::pair<unsigned short, short> > { typedef IntPairHash<unsigned short, short> Hash; };
template<> struct DefaultHash<std::pair<unsigned short, unsigned short> > { typedef IntPairHash<unsigned short, unsigned short> Hash; };
template<> struct DefaultHash<std::pair<unsigned short, int> > { typedef IntPairHash<unsigned short, int> Hash; };
template<> struct DefaultHash<std::pair<unsigned short, unsigned> > { typedef IntPairHash<unsigned short, unsigned> Hash; };
template<> struct DefaultHash<std::pair<int, short> > { typedef IntPairHash<int, short> Hash; };
template<> struct DefaultHash<std::pair<int, unsigned short> > { typedef IntPairHash<int, unsigned short> Hash; };
template<> struct DefaultHash<std::pair<int, int> > { typedef IntPairHash<int, int> Hash; };
template<> struct DefaultHash<std::pair<int, unsigned> > { typedef IntPairHash<unsigned, unsigned> Hash; };
template<> struct DefaultHash<std::pair<unsigned, short> > { typedef IntPairHash<unsigned, short> Hash; };
template<> struct DefaultHash<std::pair<unsigned, unsigned short> > { typedef IntPairHash<unsigned, unsigned short> Hash; };
template<> struct DefaultHash<std::pair<unsigned, int> > { typedef IntPairHash<unsigned, int> Hash; };
template<> struct DefaultHash<std::pair<unsigned, unsigned> > { typedef IntPairHash<unsigned, unsigned> Hash; };
// make PairHash the default hash function for pairs of arbitrary values.
template<typename T, typename U> struct DefaultHash<std::pair<T, U> > { typedef PairHash<T, U> Hash; };
} // namespace WTF
......
2012-09-14 Dana Jansens <danakj@chromium.org>
Minimize collisions when hashing pairs
https://bugs.webkit.org/show_bug.cgi?id=96022
Reviewed by Adrienne Walker.
Use WTF::pairIntHash() to hash pairs of integers.
* dom/Document.cpp:
(WebCore::ImmutableAttributeDataCacheKey::hash):
* dom/StyledElement.cpp:
(WebCore::computePresentationAttributeCacheHash):
* platform/graphics/Gradient.cpp:
(WebCore::Gradient::hash):
* platform/graphics/IntPointHash.h:
(WTF::IntPointHash::hash):
* platform/graphics/IntRectHash.h:
* platform/graphics/IntSizeHash.h:
* platform/graphics/blackberry/LayerTileIndex.h:
* platform/graphics/cg/GraphicsContextCG.cpp:
(WebCore::SubimageCacheHash::hash):
2012-09-14 Rob Buis <rbuis@rim.com>
 
[BlackBerry] Use StringBuilder more in BlackBerry RSS classes
......@@ -6322,7 +6322,7 @@ public:
unsigned hash() const
{
unsigned attributeHash = StringHasher::hashMemory(m_attributes, m_attributeCount * sizeof(Attribute));
return WTF::intHash((static_cast<uint64_t>(m_localName->existingHash()) << 32 | attributeHash));
return WTF::pairIntHash(m_localName->existingHash(), attributeHash);
}
private:
......
......@@ -266,7 +266,7 @@ static unsigned computePresentationAttributeCacheHash(const PresentationAttribut
return 0;
ASSERT(key.attributesAndValues.size());
unsigned attributeHash = StringHasher::hashMemory(key.attributesAndValues.data(), key.attributesAndValues.size() * sizeof(key.attributesAndValues[0]));
return WTF::intHash((static_cast<uint64_t>(key.tagName->existingHash()) << 32 | attributeHash));
return WTF::pairIntHash(key.tagName->existingHash(), attributeHash);
}
void StyledElement::updateAttributeStyle()
......
......@@ -33,7 +33,7 @@
#include <wtf/StringHasher.h>
#include <wtf/UnusedParam.h>
using WTF::intHash;
using WTF::pairIntHash;
namespace WebCore {
......@@ -283,7 +283,7 @@ unsigned Gradient::hash() const
unsigned parametersHash = StringHasher::hashMemory(&parameters, sizeof(parameters));
unsigned stopHash = StringHasher::hashMemory(m_stops.data(), m_stops.size() * sizeof(ColorStop));
m_cachedHash = intHash((static_cast<uint64_t>(parametersHash) << 32) | stopHash);
m_cachedHash = pairIntHash(parametersHash, stopHash);
return m_cachedHash;
}
......
......@@ -28,7 +28,7 @@ namespace WTF {
// The empty value is (0, INT_MIN), the deleted value is (INT_MIN, 0)
struct IntPointHash {
static unsigned hash(const WebCore::IntPoint& p) { return WTF::intHash(static_cast<uint64_t>(p.x()) << 32 | p.y()); }
static unsigned hash(const WebCore::IntPoint& p) { return pairIntHash(p.x(), p.y()); }
static bool equal(const WebCore::IntPoint& a, const WebCore::IntPoint& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
......
......@@ -37,7 +37,7 @@ namespace WTF {
template<> struct IntHash<WebCore::IntRect> {
static unsigned hash(const WebCore::IntRect& key)
{
return intHash(static_cast<uint64_t>(DefaultHash<WebCore::IntPoint>::Hash::hash(key.location())) << 32 | DefaultHash<WebCore::IntSize>::Hash::hash(key.size()));
return pairIntHash(DefaultHash<WebCore::IntPoint>::Hash::hash(key.location()), DefaultHash<WebCore::IntSize>::Hash::hash(key.size()));
}
static bool equal(const WebCore::IntRect& a, const WebCore::IntRect& b)
{
......
......@@ -27,7 +27,7 @@
namespace WTF {
template<> struct IntHash<WebCore::IntSize> {
static unsigned hash(const WebCore::IntSize& key) { return intHash((static_cast<uint64_t>(key.width()) << 32 | key.height())); }
static unsigned hash(const WebCore::IntSize& key) { return pairIntHash(key.width(), key.height()); }
static bool equal(const WebCore::IntSize& a, const WebCore::IntSize& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
......
......@@ -66,7 +66,7 @@ inline bool operator!=(const TileIndex& a, const TileIndex& b)
namespace WTF {
template<> struct IntHash<WebCore::TileIndex> {
static unsigned hash(const WebCore::TileIndex& key) { return intHash((static_cast<uint64_t>(key.i()) << 32 | key.j())); }
static unsigned hash(const WebCore::TileIndex& key) { return pairIntHash(key.i(), key.j()); }
static bool equal(const WebCore::TileIndex& a, const WebCore::TileIndex& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
......
......@@ -74,7 +74,7 @@ extern "C" {
using namespace std;
// FIXME: The following using declaration should be in <wtf/HashFunctions.h>.
using WTF::intHash;
using WTF::pairIntHash;
// FIXME: The following using declaration should be in <wtf/HashTraits.h>.
using WTF::GenericHashTraits;
......@@ -116,8 +116,8 @@ struct SubimageCacheEntryTraits : GenericHashTraits<SubimageCacheEntry> {
struct SubimageCacheHash {
static unsigned hash(CGImageRef image, const FloatRect& rect)
{
return intHash((static_cast<uint64_t>(PtrHash<CGImageRef>::hash(image)) << 32)
| (static_cast<unsigned>(rect.x()) << 16) | static_cast<unsigned>(rect.y()));
return pairIntHash(PtrHash<CGImageRef>::hash(image),
(static_cast<unsigned>(rect.x()) << 16) | static_cast<unsigned>(rect.y()));
}
static unsigned hash(const SubimageCacheEntry& key)
{
......
2012-09-14 Dana Jansens <danakj@chromium.org>
Minimize collisions when hashing pairs
https://bugs.webkit.org/show_bug.cgi?id=96022
Reviewed by Adrienne Walker.
Use WTF::pairIntHash() to hash a pair of integers.
* WebKitSupport/TileIndexHash.h:
2012-09-14 Genevieve Mak <gmak@rim.com>
Always send mouse events on pages that don't scroll even if there
......
......@@ -28,7 +28,7 @@ using BlackBerry::WebKit::TileIndex;
namespace WTF {
template<> struct IntHash<TileIndex> {
static unsigned hash(const TileIndex& key) { return intHash((static_cast<uint64_t>(key.i()) << 32 | key.j())); }
static unsigned hash(const TileIndex& key) { return pairIntHash(key.i(), key.j()); }
static bool equal(const TileIndex& a, const TileIndex& b) { return a == b; }
static const bool safeToCompareToEmptyOrDeleted = true;
};
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment