8282664: Unroll by hand StringUTF16 and StringLatin1 polynomial hash loops

Co-authored-by: Sandhya Viswanathan <sviswanathan@openjdk.org>
Co-authored-by: Ludovic Henry <luhenry@openjdk.org>
Co-authored-by: Claes Redestad <redestad@openjdk.org>
Reviewed-by: vlivanov, sviswanathan, luhenry
This commit is contained in:
Claes Redestad 2023-01-17 21:06:22 +00:00
parent ade08e190c
commit e37078f5bb
33 changed files with 1053 additions and 87 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -28,12 +28,19 @@ import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.TimeUnit;
import java.io.UnsupportedEncodingException;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.reflect.Method;
/**
* Performance test of String.hashCode() function
@ -83,4 +90,66 @@ public class StringHashCode {
public int empty() {
return empty.hashCode();
}
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
@State(Scope.Thread)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3, jvmArgsAppend = {"--add-exports", "java.base/java.lang=ALL-UNNAMED", "--add-opens", "java.base/java.lang=ALL-UNNAMED"})
public static class Algorithm {
private final static String alphabet = "abcdefghijklmnopqrstuvwxyz";
private final static MethodHandle defaultLatin1HashCodeMH;
private final static MethodHandle defaultUTF16HashCodeMH;
static {
try {
Class<?> stringLatin1 = Class.forName("java.lang.StringLatin1");
Method stringLatin1HashCode = stringLatin1.getDeclaredMethod("hashCode", byte[].class);
stringLatin1HashCode.setAccessible(true);
defaultLatin1HashCodeMH = MethodHandles.lookup().unreflect(stringLatin1HashCode);
Class<?> stringUTF16 = Class.forName("java.lang.StringUTF16");
Method stringUTF16HashCode = stringUTF16.getDeclaredMethod("hashCode", byte[].class);
stringUTF16HashCode.setAccessible(true);
defaultUTF16HashCodeMH = MethodHandles.lookup().unreflect(stringUTF16HashCode);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
@Param({"1", "10", "100", "10000"})
private int size;
private byte[] latin1;
private byte[] utf16;
@Setup
public void setup() throws UnsupportedEncodingException, ClassNotFoundException, NoSuchMethodException, Throwable {
Random rnd = new Random(42);
char[] str = new char[size];
for (int i = 0; i < size; i++) {
str[i] = alphabet.charAt(rnd.nextInt(alphabet.length()));
}
latin1 = new String(str).getBytes("US-ASCII");
utf16 = new String(str).getBytes("UTF-16");
// strip out byte order byte(s)
utf16 = Arrays.copyOfRange(utf16, utf16.length - str.length * 2, utf16.length);
}
@Benchmark
public int defaultLatin1() throws Throwable {
return (int)defaultLatin1HashCodeMH.invokeExact(latin1);
}
@Benchmark
public int defaultUTF16() throws Throwable {
return (int)defaultUTF16HashCodeMH.invokeExact(utf16);
}
}
}