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) { if (seed == 0) {
last = 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; last += result;
return result; return result;
} }

View File

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