Optimise ObjectsHashIterative hash function.

Avoid using Arrays.deepHashCode. The array passed to deepHashCode is
always length 2. So we can unroll the same computation for the fixed 2
iterations.
This commit is contained in:
Alex Herbert 2020-03-17 00:59:00 +00:00
parent a699c8b9ba
commit d6eeceb018
2 changed files with 13 additions and 7 deletions

View File

@ -60,7 +60,14 @@ public final class ObjectsHashIterative implements HashFunction {
if (seed == 0) {
last = 0;
}
final long result = Arrays.deepHashCode(new Object[] { last, buffer });
// Effectively:
// result = Arrays.deepHashCode(new Object[] { last, buffer });
// The method loops over items starting with result=1
// for i in items:
// result = 31 * result + hashCode(i)
// Here we unroll the computation to 2 iterations.
// The computation is done using 32-bit integers then cast to a long
final long result = 31 * (31 + Long.hashCode(last)) + Arrays.hashCode(buffer);
last += result;
return result;
}

View File

@ -41,12 +41,11 @@ public class ObjectsHashIterativeTest extends AbstractHashFunctionTest {
long l = obj.apply(buffer, 0);
long prev = 0;
assertEquals(Arrays.deepHashCode(new Object[] {prev, buffer}), l);
prev += l;
l = obj.apply(buffer, 1);
assertEquals(Arrays.deepHashCode(new Object[] {prev, buffer}), l);
prev += l;
l = obj.apply(buffer, 2);
assertEquals(Arrays.deepHashCode(new Object[] {prev, buffer}), l);
for (int i = 1; i <= 5; i++) {
prev += l;
l = obj.apply(buffer, i);
assertEquals(Arrays.deepHashCode(new Object[] {prev, buffer}), l);
}
}
@Override