mirror of
https://github.com/wren-lang/wren.git
synced 2026-01-11 06:08:41 +01:00
Merge pull request #693 from wren-lang/faster-bit-hash
Fix horrendously bad bit hashing function.
This commit is contained in:
@ -356,24 +356,18 @@ ObjMap* wrenNewMap(WrenVM* vm)
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline uint32_t hashBits(DoubleBits bits)
|
static inline uint32_t hashBits(uint64_t hash)
|
||||||
{
|
{
|
||||||
uint32_t result = bits.bits32[0] ^ bits.bits32[1];
|
// From v8's ComputeLongHash() which in turn cites:
|
||||||
|
// Thomas Wang, Integer Hash Functions.
|
||||||
// Slosh the bits around some. Due to the way doubles are represented, small
|
// http://www.concentric.net/~Ttwang/tech/inthash.htm
|
||||||
// integers will have most of low bits of the double respresentation set to
|
hash = ~hash + (hash << 18); // hash = (hash << 18) - hash - 1;
|
||||||
// zero. For example, the above result for 5 is 43d00600.
|
hash = hash ^ (hash >> 31);
|
||||||
//
|
hash = hash * 21; // hash = (hash + (hash << 2)) + (hash << 4);
|
||||||
// We map that to an entry index by masking off the high bits which means
|
hash = hash ^ (hash >> 11);
|
||||||
// most small integers would all end up in entry zero. That's bad. To avoid
|
hash = hash + (hash << 6);
|
||||||
// that, push a bunch of the high bits lower down so they affect the lower
|
hash = hash ^ (hash >> 22);
|
||||||
// bits too.
|
return (uint32_t)(hash & 0x3fffffff);
|
||||||
//
|
|
||||||
// The specific mixing function here was pulled from Java's HashMap
|
|
||||||
// implementation.
|
|
||||||
result ^= (result >> 20) ^ (result >> 12);
|
|
||||||
result ^= (result >> 7) ^ (result >> 4);
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a hash code for [num].
|
// Generates a hash code for [num].
|
||||||
@ -382,7 +376,7 @@ static inline uint32_t hashNumber(double num)
|
|||||||
// Hash the raw bits of the value.
|
// Hash the raw bits of the value.
|
||||||
DoubleBits bits;
|
DoubleBits bits;
|
||||||
bits.num = num;
|
bits.num = num;
|
||||||
return hashBits(bits);
|
return hashBits(bits.bits64);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generates a hash code for [object].
|
// Generates a hash code for [object].
|
||||||
@ -429,9 +423,7 @@ static uint32_t hashValue(Value value)
|
|||||||
if (IS_OBJ(value)) return hashObject(AS_OBJ(value));
|
if (IS_OBJ(value)) return hashObject(AS_OBJ(value));
|
||||||
|
|
||||||
// Hash the raw bits of the unboxed value.
|
// Hash the raw bits of the unboxed value.
|
||||||
DoubleBits bits;
|
return hashBits(value);
|
||||||
bits.bits64 = value;
|
|
||||||
return hashBits(bits);
|
|
||||||
#else
|
#else
|
||||||
switch (value.type)
|
switch (value.type)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -6,17 +6,17 @@ main() {
|
|||||||
|
|
||||||
var map = {};
|
var map = {};
|
||||||
|
|
||||||
for (var i = 1; i <= 1000000; i++) {
|
for (var i = 1; i <= 2000000; i++) {
|
||||||
map[i] = i;
|
map[i] = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
var sum = 0;
|
var sum = 0;
|
||||||
for (var i = 1; i <= 1000000; i++) {
|
for (var i = 1; i <= 2000000; i++) {
|
||||||
sum += map[i];
|
sum += map[i];
|
||||||
}
|
}
|
||||||
print(sum);
|
print(sum);
|
||||||
|
|
||||||
for (var i = 1; i <= 1000000; i++) {
|
for (var i = 1; i <= 2000000; i++) {
|
||||||
map.remove(i);
|
map.remove(i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -2,17 +2,17 @@ local start = os.clock()
|
|||||||
|
|
||||||
local map = {}
|
local map = {}
|
||||||
|
|
||||||
for i = 1, 1000000 do
|
for i = 1, 2000000 do
|
||||||
map[i] = i
|
map[i] = i
|
||||||
end
|
end
|
||||||
|
|
||||||
local sum = 0
|
local sum = 0
|
||||||
for i = 1, 1000000 do
|
for i = 1, 2000000 do
|
||||||
sum = sum + map[i]
|
sum = sum + map[i]
|
||||||
end
|
end
|
||||||
io.write(string.format("%d\n", sum))
|
io.write(string.format("%d\n", sum))
|
||||||
|
|
||||||
for i = 1, 1000000 do
|
for i = 1, 2000000 do
|
||||||
map[i] = nil
|
map[i] = nil
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -6,15 +6,15 @@ start = time.clock()
|
|||||||
|
|
||||||
map = {}
|
map = {}
|
||||||
|
|
||||||
for i in range(1, 1000001):
|
for i in range(1, 2000001):
|
||||||
map[i] = i
|
map[i] = i
|
||||||
|
|
||||||
sum = 0
|
sum = 0
|
||||||
for i in range(1, 1000001):
|
for i in range(1, 2000001):
|
||||||
sum = sum + map[i]
|
sum = sum + map[i]
|
||||||
print(sum)
|
print(sum)
|
||||||
|
|
||||||
for i in range(1, 1000001):
|
for i in range(1, 2000001):
|
||||||
del map[i]
|
del map[i]
|
||||||
|
|
||||||
print("elapsed: " + str(time.clock() - start))
|
print("elapsed: " + str(time.clock() - start))
|
||||||
@ -2,17 +2,17 @@ start = Time.now
|
|||||||
|
|
||||||
map = Hash.new
|
map = Hash.new
|
||||||
|
|
||||||
for i in (1..1000000)
|
for i in (1..2000000)
|
||||||
map[i] = i
|
map[i] = i
|
||||||
end
|
end
|
||||||
|
|
||||||
sum = 0
|
sum = 0
|
||||||
for i in (1..1000000)
|
for i in (1..2000000)
|
||||||
sum = sum + map[i]
|
sum = sum + map[i]
|
||||||
end
|
end
|
||||||
puts sum
|
puts sum
|
||||||
|
|
||||||
for i in (1..1000000)
|
for i in (1..2000000)
|
||||||
map.delete(i)
|
map.delete(i)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@ -2,17 +2,17 @@ var start = System.clock
|
|||||||
|
|
||||||
var map = {}
|
var map = {}
|
||||||
|
|
||||||
for (i in 1..1000000) {
|
for (i in 1..2000000) {
|
||||||
map[i] = i
|
map[i] = i
|
||||||
}
|
}
|
||||||
|
|
||||||
var sum = 0
|
var sum = 0
|
||||||
for (i in 1..1000000) {
|
for (i in 1..2000000) {
|
||||||
sum = sum + map[i]
|
sum = sum + map[i]
|
||||||
}
|
}
|
||||||
System.print(sum)
|
System.print(sum)
|
||||||
|
|
||||||
for (i in 1..1000000) {
|
for (i in 1..2000000) {
|
||||||
map.remove(i)
|
map.remove(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -86,7 +86,7 @@ BENCHMARK("for", r"""499999500000""")
|
|||||||
BENCHMARK("method_call", r"""true
|
BENCHMARK("method_call", r"""true
|
||||||
false""")
|
false""")
|
||||||
|
|
||||||
BENCHMARK("map_numeric", r"""500000500000""")
|
BENCHMARK("map_numeric", r"""2000001000000""")
|
||||||
|
|
||||||
BENCHMARK("map_string", r"""12799920000""")
|
BENCHMARK("map_string", r"""12799920000""")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user